Le point est que U
peut être de tout type qui est une sous-classe de T
et le Stack
que nous obtenons est une pile de ce type, pas de T
. Par conséquent, les éléments qui y sont ajoutés doivent être de type U
et les éléments que vous en récupérez sont garantis U
s'ils ne sont pas NULL. Toutes les joies et les peines familières de la vérification de type à la compilation.
Les éléments du Stack<T>
peuvent être de type T
ou de toute sous-classe de T
. Le nom de cette méthode suggère qu'il renvoie une pile qui contient uniquement les éléments de la pile parent qui appartiennent à une sous-classe particulière. Une fois que vous garantissez que tous les éléments de la nouvelle pile sont du type plus spécialisé, c'est beaucoup plus utile si c'est le type de la nouvelle pile.
Voici un exemple d'une manière extravagante artificielle (clairement, cette classe « stack » ne fait pas vraiment quoi que ce soit une pile ne, mais pour notre exemple, il n'a pas besoin de):
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);
}
}