18

おそらく私の Google-Fu には失敗しましたが、.NET での nullable の比較が常に他のものよりも小さいかどうかを判断できませんでした。

これに似たコードがあります

MyClass findLatest(List<MyClass> items){
    DateTime? latest_tstamp = null;
    MyClass latest_item = null;
    foreach(var item in items){
        if (latest_tstamp < item.tstamp){
            latest_tstamp = item.tstamp;
            latest_item = item;
        }
    }
    return latest_item;
}

私が試したいくつかの限られたケースではうまくいくようです(もちろんitem.tstamp宣言されています)。DateTime? tstamp

これは保証された動作ですか?

結論(?)

回答(およびJon Skeetの[別の質問への回答])に基づいて、次のチェックを行いました。

if (item.tstamp != null &&
    (latest_tstamp == null || latest_tstamp < item.tstamp)){
    // do stuff
}
4

6 に答える 6

23

これは、C# 仕様で保証されている動作です。<null 許容値型の結果はfalse、それらのいずれかが である場合ですnull。一方、参照型は異なる動作を示す場合があります。

それでも、これを使用することはお勧めしません。このコードを理解するのは難しいです。そもそもnullableを使用するのではなく、明示的なnullチェック、または単にブール値のフラグを使用したいと思います。isFirstElement

7.2.7 リフト演算子

リフト演算子を使用すると、null 非許容値型を操作する定義済みおよびユーザー定義の演算子を、それらの型の null 許容形式でも使用できます。リフト演算子は、次に説明するように、特定の要件を満たす定義済みおよびユーザー定義の演算子から構成されます。

...

  • 関係演算子
         <   >   <=   >=
    の場合、オペランドの型が両方とも null 非許容値型であり、結果の型が である場合、リフトされた形式の演算子が存在しますbool?持ち上げられた形式は、各オペランドの型に単一の修飾子を追加することによって構築されます。一方または両方のオペランドが の場合、持ち上げられた演算子は値を生成します。falsenullそれ以外の場合、リフトされた演算子はオペランドをアンラップし、基礎となる演算子を適用してbool結果を生成します。

(C# 言語仕様バージョン 3.0 より引用)

于 2012-07-11T17:06:29.780 に答える
6

MSDN からの引用:

null 許容型との比較を実行するときに、null 許容型のいずれかの値が null で、もう一方の値がそうでない場合、!=(等しくない) を除くすべての比較は false と評価されます。特定の比較が false を返すため、反対のケースが true を返すと想定しないことが重要です。次の例では、10 は null よりも大きくも小さくも等しくもありません。num1 != num2 true と評価されるだけです。

両方とも null である 2 つの null 許容型の等価比較は、true と評価されます。

于 2012-07-11T17:03:26.673 に答える
2

この場合、 になることはありませんtrue。値の 1 つがnull常に false である null 許容値間の比較では、false が生成されます。したがって、ifここで比較が真になることlatest_itemはなく、値に設定されることもありません

于 2012-07-11T17:03:13.710 に答える
0

コンパイラの規則に関係なく、コードはあまり読みやすくありません。明示的に null チェックを行う必要があります (IMO):

if (latest_tstamp == null)
于 2012-07-11T17:01:58.453 に答える
0

これは、すべての型で機能することが保証されているわけではありません。これは、<演算子をオーバーライドして特定のクラスで意味をなすことができ、そのコードが null を考慮しない可能性があるためです。の標準演算子の場合Nullable<T>、null は値より小さいと比較されます。

ただし、カスタム型を扱っている場合は、それらの演算子が null を考慮していない可能性があることを考慮してください。たとえば、次のばかげた例を見てください。

void Main()
{
    Foo x = null;
    Foo y = new Foo();

    Console.WriteLine(x < y);
    Console.WriteLine(x > y);
}

class Foo 
{
    public static bool operator <(Foo lhs, Foo rhs)
    {
        if (ReferenceEquals(lhs, null))
            return false;
        return true;
    }

    public static bool operator >(Foo lhs, Foo rhs)
    {
        return false;
    }
}

ここでの他の回答に同意します。コードが機能する可能性がありますが、明示的なnullチェックを行う方がよいでしょう。

于 2012-07-11T17:03:24.473 に答える