2010年12月6日月曜日

(C#, VB.NET)Access Nz 関数の代用

Access(アクセス) には指定した値が null だった時に別の値を返す Nz 関数という大変便利な関数があります。

VB.NET の場合 null ではなく Nothing になるので Is Nothing を活用します。また DB を扱っている場合だと DBNull を扱う場面が出てきます、その場合は IsDBNull() を活用します。両者を組み合わせる事で Nz 関数の代用が可能です。
Access に慣れている場合は同じ様に使える関数を自作しておくと使い勝手が良いです。

以下はサンプル
''' <summary>
''' オブジェクトが Nothing または DBNull の場合に長さ 0 の文字列("")または指定したその他の値を返す
''' </summary>
''' <param name="Value">対象となるオブジェクト</param>
''' <param name="ValueIfNull">Nothing または DBNull のときに返す値を指定、長さ 0 の文字列("")以外の値を返す場合に指定</param>
''' <returns>長さ 0 の文字列("")または、指定したその他の値</returns>
''' <remarks>AccessのNz関数をVB.NET版として作成。ただし数値の場合は ValueIfNull に 0 を指定しないと長さ 0 の文字列("")を返す</remarks>
Public Shared Function Nz(ByVal Value As Object, _
                          Optional ByVal ValueIfNull As Object = Nothing) As String

    Nz = ""

    Dim res As Object

    If ValueIfNull Is Nothing Then
        res = Space(0)
    Else
        res = ValueIfNull
    End If

    If IsDBNull(Value) Or Value Is Nothing Then
        Nz = res
    Else
        Nz = Value.ToString()
    End If

End Function


C# には『?? 演算子』という便利なものがあります。
    string indata = null;
    string outdata = indata ?? "null です";
この様に使えます。単純明快です。
この例だと outdata には文字列『null です』が入ります。

さらに null 許容型や as 演算子を組み合わせると DBNull とのキャストで便利に使えます。
    object dr;

//dr に decimal の値 → キャスト可能 → decimal の値
//dr に null → 例外発生
//dr に DBNull → 例外発生
    decimal r = (decimal)dr;

//dr に decimal の値 → キャスト可能 → decimal の値
//dr に null → キャスト可能 → null
//dr に DBNull → 例外発生
    decimal? r = (decimal?)dr;

//dr に decimal の値 → キャスト可能 → decimal の値
//dr に null → キャスト可能 → null → decimal の 0 を返す
//dr に DBNull → キャスト不可(as で null が返る) → decimal の 0 を返す
    decimal r = dr as decimal? ?? 0m;
3番目の内容は DBNull は null ではないので decimal? にキャストされず as 演算子で null になり ?? 演算子で 0 になります。結果的に null の場合と DBNull の場合に 0 を返します。
null と DBNull が混在する状況というのも、あまり無いとは思いますが、1行で書けて簡潔という事で。

他に Convert.IsDBNull というものもあります。DBNull を特定する用途には使えますが、それだけなら単純に == 演算子や Equals でも比較が行えるので、わざわざ書く事は無いかも?しれません。
VB.NET でも Convert.IsDBNull は使えますが IsDBNull があるのでわざわざ書く事は無いかもしれません。
VB.NET, C# 双方で共通のコーディング規約がある場合には良いかもしれません。

■環境
OS:Microsoft Windows XP Home Edition 日本語 ServicePack 3
IDE:Microsoft Visual Studio 2005 Standard Edition 日本語 Service Pack 1
Framework:Microsoft .NET Framework Version 2.0 SP2