NULL(Nothing)の扱いについて
C#/VB.NETにおいて、オブジェクトの中身がNULL(Nothing)の場合、そのオブジェクトを参照すると、NullReferenceExceptionの例外が発生してしまいます。つまり参照前にNULL判定をしてやる必要があります。
C#/VB.NETには、NULLの扱いについて、便利な演算子・構文がいろいろと追加されています。
NULL条件演算子(?.)、NULL合体演算子(??)、三項演算子(?)など検索しにくい演算子ですが使いこなせればかなり便利です。
それぞれC#, VB.NETでのサンプルコードを用意しました。
VB.NETにはNULL合体演算子(??)が存在しません。
if文での判定
まず一番単純な判定方法が、if文を使うものです。NULLでない場合のみ参照を行う方法です。コードが長くなりますが誰が見てもすぐに分かるものです。
C#
// NULL
object val = null;
// if文でNULL判定
if (val == null)
{
Console.WriteLine("NULLです ...");
}
VB.NET
Dim val As Object = Nothing
If val Is Nothing Then
Console.WriteLine("Nothingです ...")
End If
三項演算子を使う
if文での判定は複数行にわたるので、コードが長くなり可読性が劣ります。そこで三項演算子を使うことで1行のコードで判定を行えます。が、ややわかりにくいのが難点でしょうか。
三項演算子では、左の条件式がTrueの場合に、中央の式が評価され、Falseの場合は右の式が評価されます。
C#
string val1 = null;
string val2 = "あいうえお";
// 三項演算子を使って判定
Console.WriteLine(val1 == null ? "val1 は NULLです ..." : val1);
Console.WriteLine(val2 == null ? "val2 は NULLです ..." : val2);
VB.NET
Dim val1 As String = Nothing
Dim val2 As String = Nothing
Console.WriteLine(If(val1 Is Nothing, "val1 は Nothingです ...", val1))
Console.WriteLine(If(val2 Is Nothing, "val2 は Nothingです ...", val2))
NULLと空文字の判定を行う(IsNullOrEmpty)
String.IsNullOrEmpty メソッドを使用することで、指定された文字列が Null または Empty 文字列であるかどうかを判定できます。空文字の判定にはこれを使うほうがスマートです。さらにスペースの場合の判定も追加するには、IsNullOrWhiteSpace メソッド を使用できます。
C#
string val1 = null;
string val2 = "";
if (string.IsNullOrEmpty(val1))
{
Console.WriteLine("val1 NULLもしくは空文字です ...");
}
if (string.IsNullOrEmpty(val2))
{
Console.WriteLine("val2 NULLもしくは空文字です ...");
}
VB.NET
Dim val1 As String = Nothing
Dim val2 As String = ""
If String.IsNullOrEmpty(val1) Then
Console.WriteLine("val1 Nothingもしくは空文字です ...")
End If
If String.IsNullOrEmpty(val2) Then
Console.WriteLine("val2 Nothingもしくは空文字です ...")
End If
NULL合体演算子(??)を使う
NULL合体演算子(??)と呼ばれる演算子を使えば三項演算子より簡潔に判定を行えます。
??演算子の左辺がNULLの場合、右辺の式で評価され、NULL以外の場合は左辺の値がそのまま使用されます。
VB.NETにはNULL合体演算子(??)が存在しません。
C#
// NULL合体演算子(??)
string val1 = null;
Console.WriteLine(val1 ?? "NULLです ...");
// NULL許容型のintを計算
int? val2 = null;
var result = 1 + val2 ?? 2; // 1 + 2
Console.WriteLine(result);
NULL条件演算子(?.)を使う
stringやNULL許容型の値をそのまま使用する場合はNULL合体演算子や三項演算子を使えばいいのですが、オブジェクト自体がNULLかどうか判定した後にプロパティにアクセスするという処理を書く場合はNULL条件演算子(?.)を使えます。
NULL条件演算子(?.)を使ってオブジェクトのメンバにアクセスすれば、NULLの場合はNULLを返し、そうでない場合はメンバの値を返します。
このNULL条件演算子と(?.)とNULL合体演算子(??)を組み合わせてNULLの場合の処理を簡潔に書くことができます。
C#
int[] numbers = null;
// NULL条件演算子(?.)でメンバ、インデックス操作
// NULL合体演算子(??)でNULLの値を0として扱う
Console.WriteLine(numbers?.Length ?? 0); // 0
Console.WriteLine(numbers?[0] ?? 0); // 0
VB.NET
Dim numbers As Integer() = Nothing
' NULL条件演算子(?.)でメンバ、インデックス操作
Console.WriteLine(numbers?.Length) ' nothingなので空
Console.WriteLine(numbers?(0)) ' nothingなので空
NULL許容型を使う
値型は通常NULL値をとることができませんが、データベースをの値などではNULLを取る数値なども考えられます。一例として、ASP.NET MVCではNULL許容のフィールドを定義する際、モデルのプロパティでNULL許容型を使います。
使い方は単純で通常の値型変数の宣言で、型名の後ろに ? をつけてやるだけです。これでNULLもしくは元の型の値を取る新しい方を作れます。
元の型 T から NULL許容型 T? への変換は暗黙的に行なえますが、その逆はNULLの場合があるのでうまく行きません。
T? には 複数のプロパティがあり、値を取り出す際に使用します。が、実際には上ですでに使ったようにNULL合算演算子(??)を使ったほうがすっきりします。
名前 | 説明 |
---|---|
HasValue | 現在の Nullable |
Value | 有効な値を返します。NULLの場合には例外(InvalidOperationException)が発生します。 |
C#
int? val1 = null;
int? val2 = 1;
if (val1.HasValue)
{
Console.WriteLine(val1.Value);
}
if (val2.HasValue)
{
Console.WriteLine(val2.Value);
}
VB.NET
Dim val1 As Integer? = Nothing
Dim val2 As Integer? = 1
If val1.HasValue Then
Console.WriteLine(val1.Value)
End If
If val2.HasValue Then
Console.WriteLine(val2.Value)
End If
まとめ
NULL合算演算子(??)とNULL条件演算子(?.)を使うことで長くなりがちなコードを簡潔に1行で書くことができます。
ただし、VB.NETではNULL合算演算子(??)がないのでIIFもしくはif文での判定を使用する必要があります。
参考URL
こんにちは。参考になる記事、ありがとうございます。
仰る通りVB.netにNULL合体演算子(??)はありませんが、三項演算同様、if関数のオーバーロードが対応しています。
Dim val1 As String = Nothing
Console.WriteLine(If(val1, “NULLです …”))
Dim val2 As Integer?
Dim result = 1 + If(val2, 2) ‘ 1 + 2
Console.WriteLine(result)