Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adding generic constraints at runtime?

I'm pretty stumped with this so if anyone has any ideas. I have the generic method

public void Foo<TClass>(TClass item) where TClass : class
{ }

And I want to call this method from another generic method, but this generic method doesn't have the type constraint "where TClass : class"

public void Bar<T>(T item)
{
    this.Foo<T>(item);
} 

This doesn't work, I get the error

"The type 'T' must be a reference type in order to use it as parameter 'TClass'"

Which I understand. But my question is this - is there anything I can do with C# syntax in order to "filter" the generic type "T" to pass it to "this.Bar" if it is a class. Something like....

public void Bar<T>(T item)
{
    if (typeof(T).IsClass)
        this.Foo<T **as class**>();
} 

I realise I could use reflection to call Foo, but this just seems like cheating. Is there something I can do with C# to pass "T" on with the constraint at runtime?

Also - I can't change the constraint on the method "Bar" as it comes from an interface so the constraint has to match the constraint on the interface

like image 601
jcharlesworthuk Avatar asked Feb 09 '14 21:02

jcharlesworthuk


People also ask

How do you add generic constraints?

You can specify one or more constraints on the generic type using the where clause after the generic type name. The following example demonstrates a generic class with a constraint to reference types when instantiating the generic class.

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

The where clause in a generic definition specifies constraints on the types that are used as arguments for type parameters in a generic type, method, delegate, or local function.

Can a generic class have multiple constraints?

Multiple interface constraints can be specified. The constraining interface can also be generic.

What is a generic constraint?

A type constraint on a generic type parameter indicates a requirement that a type must fulfill in order to be accepted as a type argument for that type parameter.


1 Answers

The only way to call Foo without reflection, is to cast item to one of the types/classes in its hierarchy (after the proper IsClass check).

Obviously, there's only one type in its hierarchy that you know of a priori: Object.

public void Bar<T>(T item)
{
    if (typeof(T).IsClass)
        this.Foo((object) item);
} 

Edit :

Also, in one of the comments you said you added the class constraint to be to instantiate T. You don't need that, what you need is the new constraint.

like image 95
dcastro Avatar answered Oct 04 '22 18:10

dcastro