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

Test1将返回 arg1 的特定类型,而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
于 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>. 它允许您构建一个处理所有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

这完全是类型转换的问题。如果您的方法必须返回 T,那么 Test1 将不需要强制转换,并且由于 Test2 只返回一个接口,您将需要显式或隐式类型强制转换来获得最终类型。

于 2012-04-14T13:08:24.540 回答
0

通常,界面约束与例如IFoo, new()

...它允许您T完全操纵对象,创建,初始化集合等 - 并按照建议返回 T 。虽然只有接口,但您不知道它到底是哪个类(T)。

于 2012-04-14T13:27:21.500 回答