11

タイプ T を比較できるように制約したい場合は、次を使用する必要があります。

where T : IComparable

また

where T : IComparable<T>

#2が理にかなっている場合、私は頭を悩ませることができません。誰が違いを説明できますか?

4

5 に答える 5

6

次のように、両方の制約が必要になる場合があります。

where T : IComparable, IComparable<T>

これにより、タイプがインターフェイスのより多くのユーザーと互換性を持つようになりIComparableます。の汎用バージョンはIComparable、が値型である場合のIComparable<T>ボックス化を回避するのに役立ち、インターフェイスメソッドのより強く型付けされた実装を可能にします。T両方をサポートすることで、他のオブジェクトがどのインターフェースを要求しても、オブジェクトが準拠できるため、適切に相互運用できるようになります。

たとえば、ではなく、Array.SortArrayList.Sort使用します。IComparableIComparable<T>

于 2009-05-27T17:21:25.987 に答える
6

IComparable と IComparable<> の主な違いは、1 つ目はプレジェネリックであるため、任意のオブジェクトで比較メソッドを呼び出すことができるのに対し、2 つ目は同じ型を共有することを強制することです。

IComparable - CompareTo(object other);
IComparable<T> - CompareTo(T other);

タイプが最新の汎用ソリューションを実装していない古い .net 1.0 ライブラリを使用するつもりがない場合は、2 番目のオプションを使用します。ボクシングを回避し、比較で型の一致をチェックする必要がないため、パフォーマンスが向上します。また、最先端の方法で物事を行うことから得られる温かい感覚も得られます...


ジェフの非常に適切で適切な点に対処するために、タスクを実行するために必要な制約をジェネリックにできるだけ少なくすることをお勧めします。ジェネリック内のコードを完全に制御できるため、基本的な IComparable 型を必要とするメソッドを使用しているかどうかがわかります。したがって、彼のコメントを考慮して、私は個人的に次のルールに従います。

  • ジェネリックが IComparableのみを実装する型(つまり、レガシー 1.0 コード) を使用することを想定しておらず、ジェネリック内から IComparable パラメーターに依存するメソッドを呼び出していない場合は、IComparable<> 制約のみを使用します。

  • IComparable のみを実装する型を使用している場合は、その制約のみを使用し てください

  • IComparable パラメーターを必要とするメソッドを使用しているが、IComparable のみを実装する型を使用していない場合、ジェフの回答のように両方の制約を使用すると、ジェネリック型を受け入れるメソッドを使用するときにパフォーマンスが向上します。

3 番目の規則を拡張するには、作成するクラスが次のようであると仮定します。

public class StrangeExample<T> where ... //to be decided
{
    public void SortArray(T[] input)
    {
         Array.Sort(input);
    }

    public bool AreEqual(T a, T b)
    {
        return a.CompareTo(b) == 0;
    }
}

そして、それにどのような制約を課すかを決定する必要があります。SortArray メソッドは、渡される配列を必要とする Array.Sort を呼び出します。これには、IComparable を実装するオブジェクトが含まれています。したがって、IComparable 制約が必要です。

public class StrangeExample<T> where T : IComparable

これで、T の配列が Array.Sort に対して有効になり、インターフェイスで定義された有効な .CompareTo メソッドがあるため、クラスがコンパイルされて正しく動作します。ただし、IComparable<> インターフェイスも実装しない型でクラスを使用したくないことが確実な場合は、制約を次のように拡張できます。

public class StrangeExample<T> where T : IComparable, IComparable<T>

これは、AreEqual が呼び出されると、より高速で汎用的な CompareTo メソッドが使用されることを意味し、古い .NET 1.0 型では使用できないという犠牲を払って、パフォーマンス上の利点が見られます。

一方、AreEqual メソッドを持っていない場合は、IComparable<> 制約に利点がないため、削除することもできます。とにかく IComparable 実装のみを使用しています。

于 2009-05-27T17:03:39.080 に答える
2

を使用IComparable<T>すると、コンパレータを厳密に型指定できます。

あなたが持つことができます

public int CompareTo(MyType other)
{
    // logic
}

反対に

public int CompareTo(object other)
{
    if (other is MyType)
        // logic
}

たとえば、次のウィッチの例では、両方のインターフェースを実装しています。

public class MyType : IComparable<MyType>, IComparable
{
    public MyType(string name, int id)
    { Name = name; Id = id; }

    public string Name { get; set; }
    public int Id { get; set; }

    public int CompareTo(MyType other)
    {
        if (null == other)
            throw new ArgumentNullException("other");
        return (Id - other.Id > 0 ? 1 : 0);
    }

    public int CompareTo(object other)
    {
        if (null == other)
            throw new ArgumentNullException("other");
        if (other is MyType)
            return (Id - (other as MyType).Id > 0 ? 1 : 0);
        else
            throw new InvalidOperationException("Bad type");
    }
}


MyType t1 = new MyType("a", 1);
MyType t2 = new MyType("b", 2);
object someObj = new object();

// calls the strongly typed method: CompareTo(MyType other)
t1.CompareTo(t2);
// calls the *weakly* typed method: CompareTo(object other)
t1.CompareTo(someObj);

MyTypeのみで実装されている場合IComparable<MyType>、2 番目compareTo(someObj)はコンパイル時エラーです。これは、厳密に型指定されたジェネリックの利点の 1 つです。

一方、フレームワークには、非ジェネリックIComparableの likeを必要とするメソッドがありArray.Sortます。このような場合、この例のように両方のインターフェースを実装することを検討する必要があります。

于 2009-05-27T17:02:37.773 に答える
2

これらは 2 つの異なるインターフェイスです。.NET 2.0 より前はジェネリックがなかったため、.NET だけがありましたIComparable。.NET 2.0 ではジェネリックが登場し、.NET を作成できるようになりましたIComparable<T>。彼らはまったく同じことをします。ほとんどのライブラリは両方を認識しますが、基本的に IComparable は廃止されました。

コードに本当に互換性を持たせるには、両方を実装しますが、一方を他方に呼び出して、同じコードを 2 回記述する必要がないようにします。

于 2009-05-27T17:06:34.863 に答える
1

インターフェイスの厳密に型指定されたメンバーを参照できるようにするため、2 番目の制約を使用します。最初のオプションを使用する場合は、インターフェイス タイプを使用するためにキャストする必要があります。

于 2009-05-27T17:05:44.960 に答える