次のコードを検討してください。
DateTime t = DateTime.Today;
bool isGreater = t > null;
Visual Studio 2010 (C# 4、.NET 4.0) では、次の警告が表示されます。
警告 CS0458: 式の結果は常に 'bool?' 型の 'null' です
これは正しくありません。結果は常にfalse
(タイプbool
):
ここで、構造体 DateTime は>
(より大きい) 演算子をオーバーロードします。Null 非許容の構造体 (DateTime など) は、対応するNullable<>
型に暗黙的に変換できます。上記の式は、
bool isGreater = (DateTime?)t > (DateTime?)null;
これも同じ間違った警告を生成します。ここで、>
オペレーターは持ち上げられたオペレーターです。HasValue
これは、2 つのオペランドのいずれかが である場合に false を返すことによって機能しますfalse
。それ以外の場合、リフトされた演算子は 2 つのオペランドを基になる構造体にアンラップし、その構造>
体によって定義された のオーバーロードを呼び出します (ただし、一方のオペランドがそうでない場合、これは必要ありませんHasValue
)。
このバグを再現できますか? また、このバグはよく知られていますか? 私は何かを誤解しましたか?
これは、問題の演算子をオーバーロードするすべての構造体型 ( のような単純な型int
ではなく、列挙型ではない) で同じです。
(ここ==
で の代わりに使用すると>
、すべてが完全に似ているはずです (DateTime も==
演算子をオーバーロードするため)。しかし、似ていません。
DateTime t = DateTime.Today;
bool isEqual = t == null;
警告が表示されない☹ 変数の型が struct (オーバーロード==
され、 のような単純な型ではないint
) であることを認識せずに、誤って変数またはパラメーターの null をチェックする人を時々見かけます。警告が出た方がいいです。)
更新: Visual Studio 2015の C# 6.0 コンパイラ ( RoslynベースisGreater
上記の誤ったメッセージが CS0464 に変更され、正しい有用な警告メッセージが表示されます。また、isEqual
上記の警告の欠如は VS2015 のコンパイラで修正されていますが、/features:strict
.