Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Generic method with inferred generic arguments

Tags:

c#

generics

I have the following code to create an expression of a func for accessing a property of a class

public static Expression<Func<TObj, TProperty>> BuildGet<TObj, TProperty>(PropertyInfo property)
{
    Type type = typeof(TObj);
    ParameterExpression arg = Expression.Parameter(type, "x");
    var prop = Expression.Property(arg, property);

    return Expression.Lambda<Func<TObj, TProperty>>(prop, arg);
}

The problem is, is that I have to pass in TObj and TProperty even though they are known (properties on PropertyInfo class - .DeclaringType and .PropertyType).

Is there a way around this so I don't explicitly have to pass them in?

The return type must remain as Expression<Func<TObj, TProperty>>

like image 776
Andrew Bullock Avatar asked Jan 25 '26 22:01

Andrew Bullock


2 Answers

If the return type has to remain Func<TObj, TProperty> then the method has to stay generic. You will have to specify the types at compile-time. That's the thing - although PropertyInfo knows the types, that information is only available at execution time, whereas the compiler needs to know the type information in order to check that you're using the value properly, etc. It can't possibly know what the execution-time values of the properties will be.

If you could change the return type to just Expression then you could create an Expression<Func<TObj, TProperty>> with the appropriate types at execution time, but just return it as an Expression. You wouldn't be able to use the return value in a compile-time type-safe way without casting, but it may be helpful...

like image 133
Jon Skeet Avatar answered Jan 28 '26 13:01

Jon Skeet


How is the compiler supposed to infer the type of TObj? You are not passing any argument to the function that is of that type.

You could try something like this:

public static Expression<Func<TObj, TProperty>> BuildGet<TObj, TProperty>
    (TObj obj, TProperty property) { ... }

which would allow the compiler to infer the types of TObj and TProperty but that would mean you would have to refactor your method as you are using the PropertyInfo parameter currently.

like image 43
Andrew Hare Avatar answered Jan 28 '26 13:01

Andrew Hare