Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# Naked type constraints

In "C# 6.0 in a Nutshell" there is an example of naked type constarint usage:

class Stack<T>
{
  Stack<U> FilteredStack<U>() where U : T {...}
}

Honestly, I don't understand why I should use this constraint here. If I'll remove it and change U to T, result will be the same. So what's the point?

Thank you.

like image 404
Ed Akhmetshin Avatar asked Dec 10 '22 10:12

Ed Akhmetshin


2 Answers

The point is that U can be any type that is a subclass of T, and the Stack you get back is a stack of that type, not of T. Therefore, items added to it must be of type U, and items you get back out of it are guaranteed to be U if they're not null. All the familiar joys and sorrows of compile-time type checking.

The items in the Stack<T> could be of type T, or any subclass of T. The name of that method suggests that it's returning a stack that contains only the items in the parent stack that are actually of some particular subclass. Once you're guaranteeing that all the items in the new stack are of the more specialized type, it's far more useful if that's the type of the new stack as well.

Here's a wildly contrived example (clearly, this "stack" class doesn't actually do anything a stack does, but for our example it doesn't need to):

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);
    }
}
like image 121
15ee8f99-57ff-4f92-890c-b56153 Avatar answered Dec 28 '22 08:12

15ee8f99-57ff-4f92-890c-b56153


If you have a Stack<Animal> you can use FilteredStack<Dog> to get a Stack<Dog>. The point is that you want to be sure that the U passed to FilteredStack is a type derived from T but not necessarily T

like image 42
Titian Cernicova-Dragomir Avatar answered Dec 28 '22 08:12

Titian Cernicova-Dragomir