13

この方法は有効だと思いましたが、間違っていました:

static void Equals<T>(T x, T y)
{
    return x == y;    //operator == can't be applied to type T
}

仕様を読んだ後 (v3.0 では §7.2.4、v4.0 では §7.3.4):

7.2.4 二項演算子のオーバーロード解決

x op y という形式の演算 (op はオーバーロード可能な二項演算子、x は X 型の式、y は Y 型の式) は、次のように処理されます。

  • 演算演算子 op(x, y) に対して X および Y によって提供される候補ユーザー定義演算子のセットが決定されます。セットは、X によって提供される候補演算子と Y によって提供される候補演算子の和集合で構成され、それぞれが §7.2.5 の規則を使用して決定されます。X と Y が同じ型である場合、または X と Y が共通の基本型から派生している場合、共有候補演算子は組み合わせセットで 1 回だけ出現します。

  • 候補のユーザー定義演算子のセットが空でない場合、これが操作の候補演算子のセットになります。それ以外の場合は、事前定義された二項演算子 op の実装 (持ち上げられた形式を含む) が、演算の候補演算子のセットになります。特定の演算子の事前定義された実装は、演算子の説明で指定されます (§7.7 から §7.11)。

  • §7.4.3 のオーバーロード解決規則が候補演算子のセットに適用され、引数リスト (x, y) に関して最適な演算子が選択され、この演算子がオーバーロード解決プロセスの結果になります。オーバーロードの解決で最適な演算子を 1 つ選択できなかった場合、コンパイル時エラーが発生します。

ステップ 2 では、この定義済みの実装を適用する必要があると思います。

bool operator ==(object x, object y);
bool operator !=(object x, object y);

C# ではすべてが Object から派生しているためです。手順 3 でコンパイル時エラーが発生するのはなぜですか? この場合、「過負荷の解決が選択に失敗する」可能性はないと思います。

編集次のようなものを実装していたときに、この質問が頭に浮かびました。

class EnumComparer<TEnum> : IEqualityComparer<TEnum>
{
    public bool Equals(TEnum x, TEnum y)
    {
        return x == y;
    }
    public int GetHashCode(TEnum obj)
    {
        return (int)obj;
    }
}

残念ながら、式を作成してメソッドで動的に呼び出す必要がありEqualsます。

4

4 に答える 4

21

仕様を読んでよかったのですが、すぐに読むのをやめてしまいました。さらに読むと、次のようになります。


定義済みの参照型等価演算子には、次のいずれかが必要です。

  • 両方のオペランドは、参照型またはリテラル null として知られている型の値です。さらに、一方のオペランドの型からもう一方のオペランドの型への明示的な参照変換が存在します。

  • 1 つのオペランドは型 T の値であり、T は型パラメーターであり、もう 1 つのオペランドはリテラル null です。さらに、T には値型の制約がありません。

これらの条件のいずれかが true でない場合、バインド時エラーが発生します。(*)


エラーはオーバーロードの解決によるものではありません。エラーは、オーバーロードの解決で事前定義された参照型等価演算子が選択され、参照型がないことです。

コードを検討してください。T が等価演算子が定義されていない値型になるのを妨げるものは何ですか? 何もない。オブジェクト バージョンに戻ったとします。両方のオペランドが異なる場所にボックス化されるため、内容が同じであっても参照が等しくありません。それは遅く、紛らわしく、間違っているため、試すことさえ違法です。

そもそもなんでこんなことしようとしてんの?あなたのメソッドが機能した場合、実際には機能しませんが、あなたのメソッドは単に == を最初に使用するよりも悪いでしょう。この方法で世界にどのような価値を付加しようとしていますか?


(*) この文の文法上の誤りを仕様管理者に報告しました。

于 2011-04-27T17:31:55.880 に答える
9

where T : class参照比較を行うことを知っていれば、それはおそらくうまくいくでしょう。一般に、オペレーターはジェネリックをほとんどサポートしていませんが、回避策があります。MiscUtil は、ジェネリックの演算子を間接的にサポートしEqualityComparer<T>.Default.Equals(x,y)ます。それ以外の場合は、適切な選択です。

于 2011-04-27T17:30:54.563 に答える
1

これに使うのが好きEqualityComparer<T>.Defaultです。

Equalsこれはオーバーライドされたメソッドに基づいていますが、使用IEquatable<T>可能な場合はそれを使用し、それを実装する値型のボックス化を回避します。

EqualityComparer<T>.Default.Equals(x, y)
于 2011-04-27T17:47:22.777 に答える
-1

メソッドを使用し、実装する.Equals()ことを確認してくださいTIComparable

于 2011-04-27T17:30:28.467 に答える