広告あり

【C#】いろいろな”?”マークの意味と使い方

C#

C#のコードでなにかと出てくる”?”(はてな、クエスチョン、クエッション)マークですが、マークの場所や書き方によっていろいろな意味と使い方があります。そこで、今回はC#の”?”マークについて解説させていただきます。

[スポンサーリンク]

三項条件演算子:”?”と”:”(コロン)の組み合わせ

int temp = 30;
string result = temp < 20 ? "COLD!" : "HOT!";
Console.WriteLine(result);  // HOT!

“?”と”:”を組み合わせたものは三項条件演算子と呼ばれるもので、上の例の2行目のようにif文を1行で書けるようになっており、次のような構文となっています。

condition ? consequent : alternative

  • condition式がtrueの場合、consequentの結果が返ります。
    alternativeは実行されない)
  • condition式がfalseの場合、alternativeの結果が返ります。
    consequentは実行されない)

上の例をif文で書くと以下のようになります。

int temp = 30;
var result = "";
if (temp < 20)
{
    result = "COLD!";
}
else
{
    result = "HOT!";
}
Console.WriteLine(result);  // HOT!

三項条件演算子を使って書いた方がずいぶん簡潔になりますね!

null許容値型:変数宣言の型の後ろに付く”?”

int? a = 32;
int? b = null;    // nullを代入できる
b = 33;           // 数値の代入も可能
// 通常の値型への代入は型の変換が必要
// int c = a + b; // ←このようにはできない

これはnull許容値型と呼ばれるもので、値型の変数宣言で型(T)に”?”を付けて宣言するとnullを許容した型になります。null許容値型には通常の値の代入に加えてnullを代入できます。通常の値型とは別の型となるため、通常の値型に代入するにはnullチェックを行って型の変換をする必要があるので注意が必要です。

null条件演算子:変数の後ろに付く”?”+”.”(ピリオド)

DemoClass? item = null;
int? code = item?.Id;
string? name = item?.Name;
// code、name は null

// == DemoClass定義 ==
public class DemoClass
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int Price { get; set; }
}

これはnull条件演算子と呼ばれるもので、null許容値型や参照型(class、object等)を使用する際に、その変数がnullの場合はnull、null以外の場合はその値をそのまま返すようにできます。上の例の2行目では以下のようになります。

  • itemnullの場合、item?.idnullを返す
  • itemnull以外の場合、item?.iditem.idの値を返す

下記のようなnullチェックをしているのと同じ意味になります。

DemoClass? item = null;
int? code;
if (item is null)
{
    code = null;
}
else
{
    code = item.Id;
}

null許容値型や参照型の変数のメンバーにアクセス(item.id)する場合、その変数(item)がnullの状態でアクセスすると例外が発生してしまいます。これを防ぐために、null条件演算子を利用して例外を起さずにnullが返るようにします。(基本的にはそもそも変数(item)にnullが入らないようにコーディングするはずです。)

null合体演算子:”?”を2つ繋げた”??”

int? a = 32;
int? b = null;

int c = (a ?? 10) + (b ?? 34);
Console.WriteLine(c);  // 66

“??”はnull合体演算子と呼ばれるもので、“??”の左側の値がnullではない場合にその値が返され、左側の値がnullの場合は”??”の右側の値が返されます

上の例の4行目では、bがnullのため(b ?? 34)が34になり、cには32 + 33 = 66が格納されます。

null合体演算子は、これまでに解説したnull許容値型”T?”やnull条件演算子”?.”と組み合わせて以下のように使用すると役立つことが多いです!

null許容値型”T?”とnull合体演算子”??”の組み合わせ

null許容値型”T?”の値を基になる型に変換する際に、null合体演算子”??”を使用してnullの場合の値を提供できます。

int? a = null;
int b = a ?? -999;
Console.WriteLine(b);  // -999
null条件演算子”?.”とnull合体演算子”??”の組み合わせ

null条件演算子”?.”の結果がnullの場合に、代わりになる式をnull合体演算子”??”を使用して提供できます。

int getNullStringLength(string? addStr)
{
    return addStr?.Length ?? -999;
}

var len = getNullStringLength(null);
Console.WriteLine(len);  // -999

null合体代入演算子:”?”を2つ繋げて”=”(イコール)を付けた”??=”

List<int>? itemIds = null;
(itemIds ??= new List<int>()).Add(32);
itemIds.Add(34);
Console.WriteLine(string.Join("|", itemIds));  // 32|34

“??=”はnull合体代入演算子と呼ばれるもので、“??=”の左側の値がnullの場合のみ右側の式の値を左側に代入します

上の例では、2行目の始めでitemIdsがnullのためnew List<int>()が実行され、List<int>が生成されてそのまま.Add(32)が実行されます。

null合体代入演算子は、for文などのループ処理の中に上の例のような処理が入る場合や、下のようにnullチェックをして初期値を入れる場合などに使用すると便利です。

int defVal = 999;
int? value = null;

if (value is null)
{
    value = defVal;
}

null合体代入演算子を使用すると、上の例が下のように書けます。

int defVal = 999;
int? value = null;

value ??= defVal;

まとめ

今回は、C#で出てくる”?”マークの意味と使い方について解説させていただきました。コードを簡潔に書くために便利なものばかりですが、nullに関係するものが多くありました。プログラムにとってnullはなかなかやっかいな値です。nullを扱う場合は特に注意してくださいね!

[スポンサーリンク]

\ おすすめ書籍 /



この記事を書いた人
だんご丸

鉄鋼系SE歴 10年
金融系SE歴  6年
現在は音楽出版社のSE

●保有資格
初級システムアドミニストレータ
(現:ITパスポート)
基本情報技術者
応用情報技術者
情報セキュリティスペシャリスト
(現:情報処理安全確保支援士)
ネットワークスペシャリスト
情報セキュリティマネジメント
AWS認定クラウドプラクティショナー
AWS認定ソリューションアーキテクト - アソシエイト

だんご丸をフォローする
C#
[スポンサーリンク]
[スポンサーリンク]
だんご丸をフォローする
[スポンサーリンク]
タイトルとURLをコピーしました