Search code examples
c#constraintsgenericsvalue-typereference-type

Generic constraint on T to be reference type and value type simultaneously?


I have a problem with understanding how generic constraints work. I think I am missing something important here. I have enclosed my questions in the comments and would be grateful for providing some explanation.

//1st example:

class C <T, U>
    where T : class
    where U : struct, T
{
}
//Above code compiles well, 
//On first sight it looks like U might be reference type and value type
//at the same time. The only reason I can think of, is that T may be an 
//interface which struct can implement, Am I correct?

//2nd example

class CC<T, U>
    where T : class, new ()
    where U : struct, T
{
}

//I added also a reguirement for parameterless constructor
//and, much to my surprise, it still compiles what is
//a bit inexplicable for me.
//What 'U' would meet the requirement to be 
//value type, reference type and have a contructor at the same time?

Solution

  • There's nothing wrong with that. Let's look at the definition of the constraints on the type parameters:

    • T : class - The type argument T must be a reference type, including any class, interface, delegate, or array type.
    • U : struct - The type argument U must be a value type.
    • U : T - The type argument U must be or derive from the class T.

    So all you need to do is find a value type that derives from a reference type. At first that might sound impossible, but if you think a bit harder you will remember that all structs derive from the class object, so this works fine for both your examples:

    new C<object, int>();
    

    However if you swap struct and class then it won't compile:

    // Error - Type parameter 'T' has the 'struct' constraint so 'T'
    //         cannot be used as a constraint for 'U'
    class C<T, U>
        where T : struct
        where U : class, T
    {
    }