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; } }
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.
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.
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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With