为什么在C#中使用泛型约束

lys*_*cid 28 c# generics constraints

我在MSDN上阅读了一篇关于C#中泛型的优秀文章.

我脑子里浮现的问题是 - 我为什么要使用通用约束?

例如,如果我使用这样的代码:

public class MyClass<T> where T : ISomething
{
}
Run Code Online (Sandbox Code Playgroud)

我不能T在这个类中切换所有引用ISomething吗?

使用这种方法有什么好处?

Kir*_*oll 47

你问,"我不能T在这个班级中切换所有引用ISomething吗?" 所以我认为你的意思是比较:

public class MyClass<T> where T : ISomething 
{ 
    public T MyProperty { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

附:

public class MyClass 
{
    public ISomething MyProperty { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

在第二个例子中,MyProperty只保证是一个实例ISomething.在第一个例子中,MyProperty无论是什么T,即使它是特定的子类型ISomething.考虑以下具体实现ISomething:

public class MySomething : ISomething
{
    public string MyOtherProperty { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

现在,如果我们使用第一个通用示例,我们可以:

MyClass<MySomething> myClass = new MyClass<MySomething>();
Console.WriteLine(myClass.MyProperty.MyOtherProperty);
Run Code Online (Sandbox Code Playgroud)

另一方面,如果我们使用第二个例子,我们将无法访问,MyOtherProperty因为它只知道是ISomething:

MyClass myClass = new MyClass();
Console.WriteLine(myClass.MyProperty.MyOtherProperty); // Won't compile, no property "MyOtherProperty"
Run Code Online (Sandbox Code Playgroud)

另外,这些类型约束有用的原因是您可以引用MyProperty(键入T)和访问成员ISomething.换句话说,如果ISomething声明如下:

public interface ISomething 
{
    public string SomeProperty { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

然后你可以访问MyProperty.SomeProperty.如果你省略了where T : ISomething那么你将无法访问,SomeProperty因为T只知道它是类型object.


Ree*_*ore 8

类型安全.例如,假设您正在创建一个容器.您可以将某些内容传递给该容器并以适当的形式检索它,而不必在以后通过参数化容器进行任何转换.您只是定义了您愿意存储在容器中的事物类型的约束.


Dog*_*ett 5

这是差异的示例,仅使用List<>

图像列表不会是通用的,但它只会在IListElement使用通用的地方使用。现在想象一下你有一个类似这样的对象。

class Element : IListElement
{
   public string Something { get; set; }
}
Run Code Online (Sandbox Code Playgroud)

现在我可以这样做list.Add(element);,并且与真正的没有什么区别List<Element>。然而,当我检索数据时,情况就不同了,如果我使用使用的列表IListElement,那么我必须将数据转换回来,以便我可以Something从中获取数据。因此我必须这样做:

string s = ((Element)list[0]).Something;
Run Code Online (Sandbox Code Playgroud)

而使用通用我可以这样做:

string s = list[0].Something;
Run Code Online (Sandbox Code Playgroud)

省去了很多麻烦,当然它比这更进一步,但我认为你可以从中得到启发。