什么时候应该或不应该使用泛型类型约束?

Ben*_*ter 2 c# generics type-constraints c#-2.0

我有一个基类:

public abstract class StuffBase
{
    public abstract void DoSomething();
}
Run Code Online (Sandbox Code Playgroud)

还有两个派生类

public class Stuff1 : StuffBase
{
    public void DoSomething()
    {
        Console.WriteLine("Stuff 1 did something cool!");
    }
    public Stuff1()
    {
        Console.WriteLine("New stuff 1 reporting for duty!");
    }
}

public class Stuff2 : StuffBase
{
    public void DoSomething()
    {
        Console.WriteLine("Stuff 2 did something cool!");
    }
    public Stuff1()
    {
        Console.WriteLine("New stuff 2 reporting for duty!");
    }
}
Run Code Online (Sandbox Code Playgroud)

好的,现在说我有一个项目列表:

var items = new List<StuffBase>();
items.Add(new Stuff1());
items.Add(new Stuff2());
Run Code Online (Sandbox Code Playgroud)

我希望他们都能调用他们的DoSomething()方法.我可以期望只是迭代列表并调用他们的DoSomething()方法,所以让我们说我有一个方法来做这个叫做AllDoSomething()的方法只是遍历列表并完成工作:

public static void AllDoSomething(List<StuffBase> items)
{
    items.ForEach(i => i.DoSomething());
}
Run Code Online (Sandbox Code Playgroud)

以下方法的实际区别是什么?

public static void AllDoSomething<T>(List<T> items) where T: StuffBase
{
    items.ForEach(i => i.DoSomething());
}
Run Code Online (Sandbox Code Playgroud)

两种方法都是以实际的方式出现,虽然在语法上有所不同,但它们做同样的事情.

他们只是做同样事情的不同方式吗?我理解泛型和类型约束,但不明白为什么我会在这个实例中使用一种方式而不是另一种方式.

And*_*ech 6

这是因为到目前为止,C#不支持协方差.

更正式地说,在C#v2.0中,如果T是U的子类型,则T []是U []的子类型,但G不是G的子类型(其中G是任何泛型类型).在类型理论术语中,我们通过说C#数组类型是"协变"而泛型类型是"不变"来描述这种行为.

参考:http://blogs.msdn.com/rmbyers/archive/2005/02/16/375079.aspx

如果您有以下方法:

public static void AllDoSomething(List<StuffBase> items)
{
    items.ForEach(i => i.DoSomething());
}

var items = new List<Stuff2>();
x.AllDoSomething(items); //Does not compile
Run Code Online (Sandbox Code Playgroud)

就像你使用泛型类型约束一样,它会.

有关Covariance和Contravariance的更多信息,请查看Eric Lippert的一系列帖子.


其他值得一读的帖子: