c# - 変数 - ジェネリックメソッド引数のインタフェース制約



c# ジェネリック 変数 (4)

C#を正しく理解するために、ジェネリックメソッドの引数にインターフェイス制約を指定し、引数の型としてインターフェイスを指定するだけでは、実際の違いは何ですか?

public interface IFoo
{
    void Bar();
}

public static class Class1
{
    public static void Test1<T> (T arg1) where T : IFoo
    {
        arg1.Bar();
    }

    public static void Test2(IFoo arg1)
    {
        arg1.Bar();
    }
}

EDIT

私は私の例が単なる例であるので、非常に狭いことを知っています。 私はその範囲外にある違いにかなり興味があります。


Answer #1

あなたが与えた例の違いのスクラップはありません。 一方、ジェネリックバージョンを使用すると、メソッド署名を変更することなく、将来的に制約リスト( where T : IFoo, IOther )を拡張することができます。


Answer #2

あなたの特定の例では違いはありません。 しかし、次の方法を取る:

public static class Class1
{
    public static T Test1<T>(T arg1) where T : IFoo
    {
        arg1.Bar();
        return arg1;
    }

    public static IFoo Test2(IFoo arg1)
    {
        arg1.Bar();
        return arg1;
    }
}

Test1は特定のタイプのarg1を返しTest1が、 Test2はインターフェイスのみを返します。 これは流暢なインターフェースでよく使われます。

拡張例:

public interface IFoo
{
    void Bar();
}

public class Foo : IFoo
{
    // implementation of interface method
    public void Bar()
    {
    }

    // not contained in interface
    public void FooBar()
    {
    }
}


var foo = new Foo();
Class1.Test1(foo).FooBar(); // <- valid
Class1.Test2(foo).FooBar(); // <- invalid

Answer #3

それはすべてタイプキャストの問題です。 メソッドがTを返す必要がある場合、Test1はキャスティングを必要とせず、Test2はインターフェイスのみを返します。最終型を取得するには、明示的または暗黙的な型キャストが必要です。


Answer #4

私はちょうど他の人の答えに重点を置いておきたいと思います。

Test(IFoo foo)Test<T>(T foo) where T : IFooです。 List<object> (または、 objectを受け取るArrayList )とList<string>間には大きな違いがあるように、実際の違いがありList<string>

Test (IFoo foo)List<object>同様に、多態性と型継承の利点を提供します。 これは、すべてのIFoo型を扱う1つのクラスを構築することを可能にします。 しかし、時には多態性だけでなく、文字列を保持できるリストが必要な場合もありますArrayList List<string>ArrayList強く型付けされたラッパーを記述する必要はありません。

あなたのコードと同じです。 私はclass Comparer<T> where T:IFooを持っているとしましょう。 class Comparer<T> where T:IFoo 。 このクラスを使ってFoo1オブジェクトを互いに比較したり、 Foo2を互いに比較したりできますが、 Foo1Foo2を比較できないようにしたいと考えています。 強く型付けされたジェネリックメソッドはそれを強制しますが、多態型メソッドはそうしません:

public class Comparer
{
    public bool Compare1<T>(T first, T second) where T : IFoo {...}
    public bool Compare2 (IFoo first, IFoo second) {...}
}

Foo1 first = new Foo1();
Foo2 second = new Foo2();
myComparer.Compare1(first, second); // won't compile!
myComparer.Compare2(first, second); // Compiles and runs.




generics