?? 演算子の意味 (null 合体演算子) - はてな"?"記号が2つ続く演算子の意味 - C#
概要
?? 演算子の意味と動作を紹介します。
??
演算子は「null 合体演算子」と呼ばれており、nullの場合の処理を分けることができます。
「はてな"?"記号が2つ続く演算子」は、旧いC#にはない記述法のため、突然出てくると理解が難しいことがあります。
メモ
??=
演算子については
こちらの記事を参照してください。
書式
(値1 または 変数1) ?? (値2 または 変数2)
意味
??
演算子の左辺 (値1、変数1) の値が null の場合、演算子の右辺 (値2、変数2) の値を返します。
記述例
text変数がnullの場合、空文字列を返します。
text ?? "";
price変数がnullの場合、price_z変数の値を返します。
price ?? price_z;
if文での書き換え
下記コードは次のif文で書き換えられます。
int? value1;
int value2;
int value3;
value3 = value1 ?? value2;
int? value1;
int value2;
int value3;
if (value1 == null){
value3 = value2;
}else{
value3 = (int)value1;
}
/*
//または
if (value1 == null) value3 = value2; else value3 = (int)value1;
*/
プログラム例1
以下のプログラムを作成します。
UI
下図のフォームを作成します。ラジオボタン、テキストボックス、ボタンを配置します。
コード
using System;
using System.Windows.Forms;
namespace NullOperatorDemo
{
public partial class FormNullCoaleescingAssignmentOperator : Form
{
public FormNullCoaleescingAssignmentOperator()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
int? value;
if (radioButton1.Checked == true) {
value = 320;
}
else {
value = null;
}
textBox1.Text = string.Format("値は:{0:d}です", value ?? -1);
}
}
}
解説
radioButtonの選択状態によって
value
変数に代入する値を変えます。radioButton1 がチェックされている場合は320を代入しますが、
radioButton2がチェックされている場合は null を代入します。
int? value;
if (radioButton1.Checked == true) {
value = 320;
}
else {
value = null;
}
テキストボックスに値を表示します。
value ?? -1
の記述のため、
value
の値がnullの場合は -1の値が返され「値は:-1です」のメッセージがテキストボックスに表示されます。
value
の値がnullでない場合はvalueに代入された320の値が返されますので、「値は:320です」のメッセージがテキストボックスに表示されます。
textBox1.Text = string.Format("値は:{0:d}です", value ?? -1);
実行結果
プロジェクトを実行します。下図のウィンドウが表示されます。
[radioButton1]が選択された状態で[button1]ボタンをクリックします。"値は:320です"のメッセージが表示されます。
[radioButton2]をクリックしてチェックを切り替えます。チェックを切り替え後[button1]ボタンをクリックします。
"値は:-1です"のメッセージが表示されます。
プログラム例2
(コード
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace BasicOperator
{
public partial class FormMain : Form
{
public FormMain()
{
InitializeComponent();
}
public string GetValueData(int index)
{
switch (index) {
case 0:
return "Penguin";
case 1:
return null;
case 1:
return "Whale";
}
}
private void button1_Click(object sender, EventArgs e)
{
string value;
value = GetValueData(0);
textBox1.Text += string.Format("{0:d}\r\n", value.Length);
value = GetValueData(1);
textBox1.Text += string.Format("{0:d}\r\n", value.Length);
value = GetValueData(2);
textBox1.Text += string.Format("{0:d}\r\n", value.Length);
}
private void button2_Click(object sender, EventArgs e)
{
string value;
value = GetValueData(0);
textBox1.Text += string.Format("{0:d}\r\n", (value ?? "").Length);
value = GetValueData(1);
textBox1.Text += string.Format("{0:d}\r\n", (value ?? "").Length);
value = GetValueData(2);
textBox1.Text += string.Format("{0:d}\r\n", (value ?? "").Length);
}
}
}
解説
??演算子は左辺がnullであった場合は右辺の値を返します。
例
string value = "duck" ?? "penguin";
上記の場合は左辺がnullではないためvalueの値は"duck"です。
string value = null ?? "penguin";
上記の場合は左辺がnullのためvalueの値は"penguin"です。
補足
??演算子を使わずにif文で記述した場合のコード例です。??演算子を使ったほうがシンプルに記述できることがわかります。
private void button1_Click(object sender, EventArgs e)
{
string value;
value = GetValueData(0);
if (value != null) {
textBox1.Text += string.Format("{0:d}\r\n", value.Length);
}
else {
textBox1.Text += "0\r\n";
}
value = GetValueData(1);
if (value != null) {
textBox1.Text += string.Format("{0:d}\r\n", value.Length);
}
else {
textBox1.Text += "0\r\n";
}
value = GetValueData(2);
if (value != null) {
textBox1.Text += string.Format("{0:d}\r\n", value.Length);
}
else {
textBox1.Text += "0\r\n";
}
}
使用例
CS8601 : Possible null reference assignment.
CS8601 : Null 参照代入の可能性があります。
のワーニングを回避するために使用するケースもあります。
IConfigurationオブジェクトのGetConnectionString()メソッドの戻り値は
string?
型のため、null非許容型の string型に代入すると、CS8601のワーニングが発生します。
このため、GetConnectionString()メソッドの戻ちりがnullであった場合は、空文字列
""
を 代入したいです。if 文でも記述できますが、
??
を利用したほうが簡単に記述できます。
private IConfiguration _conf;
...
string connectionStr = _conf.GetConnectionString("DBConnectString");
private IConfiguration _conf;
...
string connectionStr = _conf.GetConnectionString("DBConnectString") ?? "";
string? temp_str = _conf.GetConnectionString("DBConnectString");
if (temp_str == null) {
connectionStr = "";
}
else {
connectionStr = temp_str;
}
著者
iPentecのメインプログラマー
C#, ASP.NET の開発がメイン、少し前まではDelphiを愛用