11

辞書のキーとしてLinq式を使用することを検討しています。ただし、Linq式によって平等がどのように決定されるかわからないため、奇妙な結果が得られるのではないかと心配しています。

式から派生したクラスは、値の同等性または参照の同等性を比較しますか?言い換えれば、

        Expression<Func<object>> first = () => new object(); 
        Expression<Func<object>> second = ()=>new object();
        bool AreTheyEqual = first == second;
4

3 に答える 3

11

テストでは式を比較します。式自体は、参照の同等性のみを提供します。テストではおそらく「false」が表示されます。セマンティックの平等を求めるには、多くの作業を行う必要があります。たとえば、次のとおりです

x => 123

y => 123

同等?大まかなテストとして、ToString()を比較できますが、これは非常に脆弱です。

于 2011-02-17T18:22:37.770 に答える
0

他の人が指摘しているように、Expressionの==演算子は、デフォルトの「参照の同等性」チェックを使用します-「両方ともヒープ内の同じ場所への参照ですか?」これは、式のリテラルがセマンティックの同等性に関係なく異なる式インスタンスとしてインスタンス化されるため、例のようなコードはfalseを返す可能性が高いことを意味します。ラムダをイベントハンドラーとして使用することにも同様のフラストレーションがあります。

MyEvent += (s, a) => DoSomething();
...
MyEvent -= (s, a) => DoSomething(); //<-- will NOT remove the added handler

セマンティックの同等性をチェックするのは難しいです。この特定のケースでは、式ツリーのすべてのノードにアクセスし、すべての文字列、値型、およびメソッド参照を比較して、それらが同じことを行うことを確認できる場合があります。ただし、調べてみると、次の例の2つのラムダは意味的に同等ですが、それを証明するメソッドを作成するのは難しいでしょう。

   public void MyMethod() {...}
   public void AnotherMethod { MyMethod(); };

   ...

   Action one = () => MyMethod();
   Action two = () => AnotherMethod();

   var equal = one == two; // false
于 2011-02-17T18:39:03.280 に答える
0

値型ではない2つのオブジェクト(式を含む)を==と比較すると、オブジェクト参照が比較されるため、等しくなりません。ただし、コメンターが指摘したように、辞書はとを使用EqualsGetHashCodeて等式を決定しますが、それでもデフォルトでは、それらは等しくないと判断することになります。

System.Linq.Expressionただし、継承してオーバーライドするクラスを作成し、結果を何らかの方法GetHashCodeEquals使用して、それを辞書のキーとして使用することもできます。

于 2011-02-17T18:25:23.107 に答える