2012-05-10 13 views
2

次の[c#]コードはコンパイルできません。 "演算子==は 'T'と 'T'型のオペランドには適用できません。ジェネリッククラスは、入力パラメータとオブジェクトが同じ型を持つように制約するメソッドです。T

public class Widget<T> where T: IComparable 
{ 
    public T value; 
    public Widget(T input) { value = input; } 
    public bool Equals<T>(Widget<T> w) where T : System.IComparable 
    { 
     return (w.value == value); 
    } 
} 

オブジェクトは、それらが互いに比較し、コンパイラエラーをなくすことができる保証こうして比較されるものと同じタイプTであるとWの入力パラメータの型Tを制約する方法はありますか?以下のように値の前に(動的)を使用すると、それはコンパイルすることができますが、コンパイル時に問題をキャッチするだろうより良い方法があるだろうと同じようには思えた:

public bool Equals<T>(Widget<T> w) where T : System.IComparable { return (w.value == (dynamic) value); }

+1

*正確に '=='をチェックしますか?参照平等?価値の平等? –

答えて

3

あなたが本当に興味を持っていると仮定すると、ここでの値の平等で、あなただけのEqualityComparer.Defaultを使用することができます。現在あなたEquals方法が一般的すぎる

EqualityComparer<T> comparer = EqualityComparer<T>.Default; 
return comparer.Equals(w.value, value); 

注、私はyとは思わない型パラメータTを宣言しようとしています本当にそうしたいと思っています。

+0

ありがとうございます。これは問題の世話をした。 – user1387916

0
public class Widget<T> where T: IComparable 
{ 
    public T value; 
    public Widget(T input) { value = input; } 
    public bool Equals(Widget<T> other) 
    { 
     if(value == null) 
     { 
      return other == null || other.Value == null; 
     } 
     if(other == null) return false; //ensure next line doesn't get null pointer exception 
     return value.CompareTo(other.Value) == 0; 
    } 
} 

あなたは、あなたはそれがvalueの様々な順列で動作するようにする方法に基づいてヌルチェックロジックで遊んでする必要がother、およびother.valueがnullであることがあります。

+0

これは、比較がequalsと一貫していると仮定しています - 必ずしもそうでないかもしれません。 –

+0

@JonSkeet合意。 Tが「IComparable」であることを確実にするためにOPがすべて努力されたことを考慮して、私は同等の実装が 'Equals'実装以上のものであると仮定しました。 – Servy

0

これは必要なものですか?

public class Widget<T> : IEquatable<Widget<T>>, IComparable<Widget<T>> 
    where T : IEquatable<T>, IComparable<T> 
{ 
    public T value; 
    public Widget(T input) { value=input; } 
    public override bool Equals(object obj) 
    { 
     if(obj is Widget<T>) 
     { 
      return Equals(obj as Widget<T>); 
     } 
     return false; 
    } 
    public override int GetHashCode() 
    { 
     return value.GetHashCode(); 
    } 
    public bool Equals(Widget<T> other) 
    { 
     return value.Equals(other.value); 
    } 

    public int CompareTo(Widget<T> other) 
    { 
     return value.CompareTo(other.value); 
    } 
    public static bool operator==(Widget<T> a, Widget<T> b) 
    { 
     return a.Equals(b); 
    } 
    public static bool operator!=(Widget<T> a, Widget<T> b) 
    { 
     return !a.Equals(b); 
    } 
    public static bool operator<(Widget<T> a, Widget<T> b) 
    { 
     return a.CompareTo(b)==-1; 
    } 
    public static bool operator>(Widget<T> a, Widget<T> b) 
    { 
     return a.CompareTo(b)==1; 
    } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     Widget<int> a=new Widget<int>(100); 
     Widget<int> b=new Widget<int>(200); 

     if(a==b||a>b) 
     { 
     } 
    } 
} 
+0

'value'と' w'をヌルにする必要があります – Servy

+0

'value'をチェックする必要がありますが、' equals() 'と' CompareTo() 'として' other'や 'obj'をチェックする必要はありません。また、 – ja72

+0

'return value.Equals(other.value);行に他のものがnullの場合はnullポインタエラーが発生します。 'other.value'はnullでもかまいませんが、' other'がnullの場合はコードが爆発します。同じ問題は 'CompareTo'の同じ行に適用されます。 – Servy

0
public class Widget<T> where T: IEquatable<T> 
{ 
    public T value; 
    public Widget(T input) { value = input; } 
    public bool Equals(Widget<T> w) 
    { 
     return (w.value.Equals(this.value)); 
    } 
} 

あなたは平等比較が必要な場合は、IEquatableを使用する必要があります。 IComparableは、順序比較も(より小さい、より大きい)場合に適しています。

あなたの主な間違いは、あなたのEquals<T>メソッドで新しいタイプのパラメータを導入していると思います。しないでください。代わりに、Widget<T>パラメータのTが、そのクラスがインスタンス化されたのと同じ型になるようにします。これにより、はthis.valueと同じタイプになります。

+0

あなたは 'w'と' w.value'をチェックする必要があります。 – Servy

+0

@セイビー:それは問題のポイントではありませんでした。もしpedanticを得たいなら 'value'フィールドはprivateでなければなりません。' widget(T) 'コンストラクタは' input'が 'null'なら' ArgumentNullException'を投げ、 'IEquatable .Equals'メソッドの実装はそのパラメータが 'null'の場合は' false'を返します。だから、「w」や「w.value」をチェックする必要はありません。 – Douglas

+0

あなたは何もする必要はありません。これらの値をチェックするのが最善です。そうしないと、あなたが防ぐことができる例外を引き起こす確率がかなり高くなります。他に何もない場合、OPには答えがない場合でもnullチェックを追加する必要があります。プライベートな 'value'に関しては、実際にはより良いデザインになりますが、そうしないとプログラムがクラッシュすることはありません。これは' ArgumentNullException'を投げない場合もそうです。 (実際には、 'input'がヌルであることは完全に受け入れられるかもしれません。) – Servy

関連する問題