Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why can't I use 'as' with generic type parameter that is constrained to be an interface?

Tags:

In the example below (only for demo purpose), if T is not constrained with class, then this conversion:

var ret = objectA as T; 

..will cause the following compile error:

The type parameter 'T' cannot be used with the 'as' operator because it does not have a class type constraint nor a 'class' constraint.

I cannot understand why I can't do this. Since I have constrained T to be interface IObject, the compiler should know that T must be an interface type and the as operation should be valid.

public interface IObject {     string Id { get; set; } } public class ObjectA : IObject {     public string Id { get; set; } } public class ObjectFactory {     public T CreateObject<T>(string id) where T : IObject     {         ObjectA objectA = new ObjectA();         var x = objectA as IObject; // this is good         var ret = objectA as T; // why this 'as' cannot compile?         return ret;     }     public T CreateClassObject<T>(string id) where T : class, IObject     {         ObjectA objectA = new ObjectA();         var ret = objectA as T; // if T is class, this 'as' can compile         return ret;     } } 
like image 238
ricky Avatar asked Jan 05 '18 07:01

ricky


People also ask

Can generic classes be constrained?

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. The code below constrains a class to an interface.

What keyword allows you to put constraints on a generic type?

So here is the list of some of the constraints that you can add to the generic classes, using the where keyword: Restrict the generic class to use the type parameter of value or reference type only (as we discussed above). Restrict the type parameter T, to be implementing the specified interface.

Which of the following generic constraints restricts the generic type parameter to an object of the class?

Value type constraint If we declare the generic class using the following code then we will get a compile-time error if we try to substitute a reference type for the type parameter.

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.


1 Answers

since I have constrained T to be interface IObject, compiler should know that T must be an interface type and the 'as' operation should be valid.

No, T doesn't have to be an interface type. It has to be a type that implements the interface. Consider:

public struct Foo : IObject {     public string Id { get; set; } } 

Now what would you expect CreateObject<Foo>("ff") to do?

With the class constraint on CreateObject, that call wouldn't be valid because Foo isn't a reference type - the compiler knows that T is a reference type, so objectA as T is okay.

like image 101
Jon Skeet Avatar answered Oct 12 '22 12:10

Jon Skeet