Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?
like image 665
nan Avatar asked Jan 09 '11 16:01

nan


People also ask

Can a generic class have multiple constraints?

There can be more than one constraint associated with a type parameter. When this is the case, use a comma-separated list of constraints. In this list, the first constraint must be class or struct or the base class.

What are generic type constraints?

C# allows you to use constraints to restrict client code to specify certain types while instantiating generic types. It will give a compile-time error if you try to instantiate a generic type using a type that is not allowed by the specified constraints.

Which of the following constraint should be used to create a generic class that should only work with reference types?

Reference type constraint This type of constraint specifies that the type argument should be a reference type. If we try to substitute a non-reference type for the type argument then we will get a compile-time error.

What does the generic constraint of type interface do?

Interface Type Constraint You can constrain the generic type by interface, thereby allowing only classes that implement that interface or classes that inherit from classes that implement the interface as the type parameter.


1 Answers

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
{
}
like image 95
Mark Byers Avatar answered Oct 19 '22 06:10

Mark Byers