C#裸类型约束

C#裸类型约束,c#,generics,generic-constraints,C#,Generics,Generic Constraints,在“C#6.0简言之”中,有一个裸体型警察用法的例子: class Stack<T> { Stack<U> FilteredStack<U>() where U : T {...} } 类堆栈 { 堆栈FilteredStack(),其中U:T{…} } 老实说,我不明白为什么我应该在这里使用这个约束。如果我删除它并将U更改为T,结果将是相同的。那有什么意义呢 谢谢。重点是U可以是T的子类的任何类型,而您返回的堆栈是该类型的堆栈,而不是T。因此,添加到

在“C#6.0简言之”中,有一个裸体型警察用法的例子:

class Stack<T>
{
  Stack<U> FilteredStack<U>() where U : T {...}
}
类堆栈
{
堆栈FilteredStack(),其中U:T{…}
}
老实说,我不明白为什么我应该在这里使用这个约束。如果我删除它并将U更改为T,结果将是相同的。那有什么意义呢


谢谢。

重点是
U
可以是
T
的子类的任何类型,而您返回的
堆栈
是该类型的堆栈,而不是
T
。因此,添加到其中的项目必须是
U
类型,并且从中获取的项目如果不为null,则保证为
U
。所有熟悉的编译时类型检查的喜怒哀乐

堆栈中的项可以是
T
类型,也可以是
T
的任何子类。该方法的名称表明它返回的堆栈仅包含父堆栈中实际属于某个特定子类的项。一旦您保证新堆栈中的所有项都是更专门化的类型,如果这也是新堆栈的类型,那么它就更有用了

下面是一个精心设计的示例(很明显,这个“stack”类实际上并不做stack所做的任何事情,但在我们的示例中,它不需要这样做):

公共A类
{
公共A(字符串s)
{
SA=s;
}
公共字符串SA{get;set;}
}
B级:A级
{
公共B(字符串s、字符串s1)
{
SA=s;
SB=s1;
}
公共字符串SB{get;set;}
}
类堆栈
{
堆栈FilteredStack(),其中U:T
{
返回新堆栈(Items.OfType());
}
公共IEnumerable项{get{return\u Items;}}
公共静态无效测试()
{
var s1=新堆栈(new[]{new A(“A1”)、new B(“B1”、“某些其他值”)});
var s2=s1.FilteredStack();
//s2是类型B的强类型堆栈
Console.WriteLine(s2.Items.First().SB);
}
私有列表_items=新列表();
公共堆栈(IEnumerable项){
_项目=新列表(项目);
}
}

如果你有一个
堆栈
,你可以使用
FilteredStack
来获得一个
堆栈
。关键是您要确保传递给
FilteredStack
U
是从
T
派生的类型,但不一定是
T
泛型约束用于限制泛型类型、函数等的访问

其中U:T表示只有从U继承的类才能访问函数FilteredStack()。那些不是从U继承的类的对象不应该能够访问FilteredStack(),它将给出编译错误。这就是类型安全的全部目的

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