何时应该或不应该使用泛型约束? [英] When should or shouldn't I be using generic type constraints?

查看:143
本文介绍了何时应该或不应该使用泛型约束?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个基类:

  public abstract class StuffBase 
{
public abstract void DoSomething();
}

和两个派生类

  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 东西2做了一件很酷的事!);

public Stuff1()
{
Console.WriteLine(New stuff 2 reporting for duty!);


好的,现在说我有一份清单items:

  var items = new List< StuffBase>(); 
items.Add(new Stuff1());
items.Add(new Stuff2());

我希望他们都调用他们的DoSomething()方法。我可以期望迭代列表并调用它们的DoSomething()方法,所以我们可以说我有一个方法可以完成名为AllDoSomething()的方法,它只是迭代列表并完成任务:

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

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

  public static void AllDoSomething< T>(List< T> items)其中T:StuffBase 
{
items.ForEach(i => i.DoSomething());

$ / code>

这两种方法虽然在语法上有所不同,同样的事情。



他们做同样的事情只是不同的方式吗?我了解泛型和类型约束,但不明白为什么我会在这种情况下使用其他方法。

是因为至今为止,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); //不会编译

如果您使用泛型类型约束,它会。



有关协方差和反变量的更多信息,请查看 Eric Lippert的一系列贴子






阅读:


I've got a base class:

public abstract class StuffBase
{
    public abstract void DoSomething();
}

And two derived classes

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!");
    }
}

Okay, now say I've got a list of items:

var items = new List<StuffBase>();
items.Add(new Stuff1());
items.Add(new Stuff2());

and I want them all to call their DoSomething() method. I could expect to just iterate the list and call their DoSomething() method, so let's say I've got a method to do that called AllDoSomething() that just iterates over the list and does the job:

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

What is the practical difference of the following method?

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

Both methods appear in real terms, although being syntactically different, to be doing the same thing.

Are they just different ways of doing the same thing? I understand generics and type constraints but can't see why I would use one way over the other in this instance.

解决方案

This is because as of yet, C# does not support Covariance.

More formally, in C# v2.0 if T is a subtype of U, then T[] is a subtype of U[], but G is not a subtype of G (where G is any generic type). In type-theory terminology, we describe this behavior by saying that C# array types are "covariant" and generic types are "invariant".

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

If you have the following method :

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

var items = new List<Stuff2>();
x.AllDoSomething(items); //Does not compile

Where as if you use the generic type constraint, it will.

For more information about Covariance and Contravariance], check out Eric Lippert's series of posts.


Other posts worth reading :

这篇关于何时应该或不应该使用泛型约束?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆