【问题标题】:C# Naked type constraintsC# 裸类型约束
【发布时间】:2017-08-30 18:31:28
【问题描述】:
在“C# 6.0 in a Nutshell”中有一个裸类型约束用法的示例:
class Stack<T>
{
Stack<U> FilteredStack<U>() where U : T {...}
}
老实说,我不明白为什么我应该在这里使用这个约束。如果我将其删除并将 U 更改为 T,结果将是相同的。那有什么意义呢?
谢谢。
【问题讨论】:
标签:
c#
generics
generic-constraints
【解决方案1】:
关键是U 可以是T 的子类的任何类型,而您返回的Stack 是那个 类型的堆栈,而不是T .因此,添加到其中的项目必须是U 类型,如果它们不为空,则从其中返回的项目保证为U。所有熟悉的编译时类型检查的喜怒哀乐。
Stack<T> 中的项目可以是T 类型,或T 的任何子类。该方法的名称表明它返回的堆栈仅包含父堆栈中实际上属于某个特定子类的项。一旦您保证新堆栈中的所有项目都是更专业的类型,那么如果这也是新堆栈的类型,它会更加有用。
这是一个非常人为的例子(显然,这个“堆栈”类实际上并没有做堆栈所做的任何事情,但对于我们的例子来说它不需要):
public class A
{
public A(String s)
{
SA = s;
}
public String SA { get; set; }
}
public class B : A
{
public B(String s, string s1)
{
SA = s;
SB = s1;
}
public String SB { get; set; }
}
class Stack<T>
{
Stack<U> FilteredStack<U>() where U : T
{
return new Stack<U>(Items.OfType<U>());
}
public IEnumerable<T> Items { get { return _items; } }
public static void Test()
{
var s1 = new Stack<A>(new[] { new A("A1"), new B("B1", "Some other value") });
var s2 = s1.FilteredStack<B>();
// s2 is a strongly typed stack of type B
Console.WriteLine(s2.Items.First().SB);
}
private List<T> _items = new List<T>();
public Stack(IEnumerable<T> items) {
_items = new List<T>(items);
}
}
【解决方案2】:
如果您有Stack<Animal>,您可以使用FilteredStack<Dog> 获取Stack<Dog>。关键是您要确保传递给FilteredStack 的U 是从T 派生的类型,但不一定是T
【解决方案3】:
泛型约束用于限制泛型类型、函数等的访问。
其中 U : T 表示只有从 U 继承的那些类才能访问函数 FilteredStack()。那些不是从 U 继承的类的对象不应该能够访问 FilteredStack() 并且它会给出一个编译错误。这就是类型安全的全部目的