11

次のコードを検討してください。

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.

4

3 に答える 3

9

Roslyn で持ち上げられたオペレーターの動作を実装しているときに、このエラーを個別に発見し、Roslyn でそれを修正してから出発しました。

10月に投稿したときに見れなかったのが残念です。Connect に送信していただきありがとうございます。そして、エラーについてお詫び申し上げます。これは、オペレーターのセマンティック分析における長年のエラーです。

ちなみに、Roslyn がリフトされた式を最適化する方法については、今月後半 (2012 年 12 月)にhttp://ericlippert.comで説明する予定です。

http://ericlippert.com/2012/12/20/nullable-micro-optimizations-part-one/

于 2012-12-19T00:26:02.780 に答える
5

正解です。これはVisualStudioのバグです。C#4.0標準(§7.3.7リフトされた演算子)には、次のように書かれています。

関係演算子の場合

<  >  <=  >=

[…]リフトされた演算子は、false一方または両方のオペランドがnullの場合に値を生成します。…</p>

実際、MonoDevelopでは、代わりに次の警告が表示されます。

System.DateTimeタイプをと比較した結果nullは常にfalseです。

于 2012-10-24T09:39:52.840 に答える
1
DateTime t = DateTime.Today;

bool isGreater = (DateTime?)t > (DateTime?)null;

このシナリオでは、警告の内容はt > null. それは決して真実ではありません。評価できないからです。

このシナリオでは:

bool isGreater = (DateTime?)t > (DateTime?)null;

評価中 (DateTime?)t > (DateTime?)nullです。

または本質的に最良のシナリオではt > null。前と同じ。DateTime.Now は Undefined よりも大きくなることはありません。したがって、警告が表示されます。

于 2012-10-24T09:19:21.810 に答える