2013-04-18 10 views
5

今日、私はVB.net If()ステートメントの奇妙な動作を見つけました。たぶんあなたはそれがそうであるように働いている理由、またはおそらくあなたがバグであることを確認することができます説明することができます。If()ステートメントの奇妙な動作

私はNULLを含むことができるint列 "NullableColumn"を持つテーブル "TestTable"を持つSQLデータベースを持っています。私はこのコラムの内容を読みたいと思います。

だから私は「のTestTable FROM NullableColumnを選択」と、この列の内容を取得するには、次のコードを使用するためにSqlClient.SqlDataReaderを開いて、そのことについてはタイプNullable(Of Integer)の変数を宣言:

Dim content as Nullable(Of Integer) 

... 

Using reader as SqlClient.SqlDataReader = ... 
    content = If(reader.IsDBNull(reader.GetOrdinal("NullableColumn")), Nothing, reader.GetInt32(reader.GetOrdinal("NullableColumn"))) 
End Using 

しかし、私のその後変数contentの値は0で、Nothingではなく予想通りです。すべてをデバッグするよう

  • reader.GetOrdinal("NullableColumn")がこの列の内容が実際
  • NULLであるため
  • reader.IsDBNull(0)reader.IsDBNull(reader.GetOrdinal("NullableColumn"))(0)このカラムの正しい順序位置は、Trueを送達する送達、申し分なく見える

  • If(1=2, Nothing, "Not Nothing")は、「何もない」文字列を返します。
  • If(1=1, Nothing, "Not Nothing")Nothing
  • reader.GetInt32(reader.GetOrdinal("NullableColumn")) NULLだからInteger

に変換することはできませんので、なぜ私の変数が値0を持っているん、エラーがスローされますか?

+0

あなたは、通常の場合に使用しました - そして - elese文を次のように

<Extension> _ Public Shared Function GetNullable(Of T)(SqlClient.SqlDataReader this, String fieldName) As T? Dim i = this.GetOrdinal(fieldName) Return If(this.IsDBNull(i), New T?(), this.GetFieldValue(Of T)(i)) End Function 

今、あなたはそれを使用することができますか?それは動作しますか? –

+0

興味のないあなたは 'Option Strict'を有効にしていますか?もしあなたがそうでなければ –

+0

はい、私は通常の 'If ... Then ... Else ...' statemantを試して、これはうまくいきました。 Option Strictをオンにしても何も変わらない。 – Nostromo

答えて

5

VBでは何もnullと同じではありません。 If演算子は、渡された引数に基づいて結果の型を判断する必要があります。もちろん、型がないため、If演算子がコード内で返すことのできる唯一の型はInt32です。 IsDBNullメソッドがtrueを返した場合、If演算子はInt32としてNothingキャストを返します。 VBでは、Nothingは型の既定値を返します。 Int32の場合、デフォルト値は0です。何もキーワードのMSDNから

Nothing represents the default value of a data type. The default value depends 
on whether the variable is of a value type or of a reference type. 

For non-nullable value types, Nothing in Visual Basic differs from null in C#. 
In Visual Basic, if you set a variable of a non-nullable value type to Nothing, 
the variable is set to the default value for its declared type. In C#, if you 
assign a variable of a non-nullable value type to null, a compile-time error 
occurs. 

私は普通の場合には、最高の仕事だと思う:

If Not reader.IsDBNull(reader.GetOrdinal("NullableColumn")) Then 
    content = reader.GetInt32(reader.GetOrdinal("NullableColumn")) 
End If 

か短い

クリスが与えた
If Not reader.IsDBNull(reader.GetOrdinal("NullableColumn")) Then content = reader.GetInt32(reader.GetOrdinal("NullableColumn")) 
1

しかし、私が期待していたとして、私の変数contentが値0、ないNothingを持っていることを後に。

どのようにcontentの値を確認しますか?

まず、content.HasValueプロパティから始める必要があります。正しい値がデータベースから取得された場合は、NothingTrueの場合はFalseにする必要があります。

価値がない場合は、content.Valueにアクセスしている間にInvalidOperationExceptionにもアクセスする必要があります。

+0

デバッグモードでマウスを変数に移動すると、この変数の内容が表示されます。 null可能なオブジェクト型は、値を持たない場合は 'Nothing'を、そうであれば実際の値を表示します。 通常の 'If ... Then ... Else ...'ステートメントを使用すると、Intellisenseは 'Nothing'を表示します.' If(...)'ステートメントを使用すると、Intellisenseは0を表示します。 – Nostromo

1

を、それを維持します説明はありますが、変数の宣言から割当てを分割するため、彼が選んだ割り当てのスタイルは嫌いですに。

これに対して、宣言時に変数を初期化することをお勧めします。この場合は、Ifのどちらかの演算子を正しい型にキャストする必要があるため、これはちょっと複雑です。

Dim content = If(reader.IsDBNull(reader.GetOrdinal("NullableColumn")), 
       DirectCast(Nothing, Integer?), 
       reader.GetInt32(reader.GetOrdinal("NullableColumn"))) 

実際にあなたが代わりDirectCastNew Integer?()少し短いを使用することができます。もちろん

contentUsingブロック内で宣言されている - これはあなたが望むものではないかもしれませんが、あなたは、可能な限りローカルとして宣言をするためにを試してみてください。

さらに、このコードは複雑で、おそらく再利用されます。私はnullablesに、データベースのNULL値を変換するために、別々の(拡張子)メソッドを作成することをお勧め:

Dim content = reader.GetNullable(Of Integer)("NullableColumn")