17

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();
    }
}

編集

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

4

5 に答える 5

12

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

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;
    }
}

Test1Test2インターフェイスのみを返すのに対し、arg1 の特定の型を返します。これは、流暢なインターフェースでよく使用されます。


拡張例:

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
于 2012-04-14T13:04:58.273 に答える
6

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

于 2012-04-14T13:06:55.850 に答える
4

他の方の回答を参考にさせていただきたいと思います。

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

Test (IFoo foo)は、 と同様に、ポリモーフィズムと型継承の利点を提供しますList<object>。すべてのタイプを処理する 1 つのクラスを作成できますIFoo。しかし、ポリモーフィズムだけではなく、文字列のみを保持できるリストがList<string>必要な場合もありますArrayList

あなたのコードも同じです。私が持っているとしましょう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.
于 2012-04-14T13:42:25.587 に答える
0

多くの場合、インターフェイスの制約は、たとえばと組み合わされますIFoo, new()

...これにより、オブジェクトをT完全に操作し、コレクションを作成、初期化することができます.-そして、提案されているように T を返します。インターフェースだけでは、それが実際にどのクラス (T) なのかわかりません。

于 2012-04-14T13:27:21.500 に答える
0

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

于 2012-04-14T13:08:24.540 に答える