1

I have a generic function as follows:

public static T Function<T>(Argument arg)
{
    //DO FUNCTION STUFF
}

I want to call this function using a Type I get from FieldInfo.FieldType like so:

Function<someFieldInfo.FieldType>(arg);

However, this is not allowed. And neither is:

Function<typeof(SomeType)>(arg);

I am far from a C# expert so excuse if this is a stupid question. But why doesn't this work? And how can I work around it to get similar functionality?

  • 1
    You can either do this with reflection or you can create an overload that takes a type argument. This is commonly used throughout the framework. – silkfire Jun 24 '17 at 17:55
  • 1
    @silkfire excuse my stupidity, but how would I do that with reflection? (Very new to this). And your other alternative. You mean to make an overload function like: Function(Type type)? I haven't reallt understod what a Type really is and why it cant be written into <>'s like you can – Eric Johansson Jun 24 '17 at 18:00
  • 2
    A function with that signature is just hiding a cast, so you might as well add an overload `public static object Function(Type t, Argument arg)` and call that: `Function(someFieldInfo.FieldType, arg)`. – Lee Jun 24 '17 at 18:08
  • @Lee Works like a charm, thank you :D But why can't you call a generic function with a type like `Function();` or `Function();` – Eric Johansson Jun 24 '17 at 18:23
  • 2
    Type parameters are resolved statically, while `someFieldInfo.FieldType` and `typeof(SomeClass)` returns a `Type` instance which is runtime representation of a type. In `var x = Function` what would you expect the type of `x` to be? – Lee Jun 24 '17 at 18:36
  • @Lee Well that depends on what the function returns ;) But I see what you mean. If `var x = someFieldInfo.FieldType` x would be an instance of a ´Type´. Since "Type parameters are resolved statically" I asume there is no way to go from a `Type` instance to a type paramater. Or am I wrong? – Eric Johansson Jun 24 '17 at 18:48
  • 1
    What are you trying to achieve? Maybe you are using the wrong approach to solve your specific problem. Assuming that `T` must implement an interface, you might returns that interface instead. – Phil1970 Jun 24 '17 at 20:00

2 Answers2

1

Since you can't accept a comment as an answer I just thought I would write it hear.

First Question: Why can't you pass the Type you get from fieldInfoInstance.FieldType to a generic function

If I have understood everything correctly, it is as @Lee pointed out, what is returned from fieldInfoInstance.fieldType is an instance of a class that extends type where as a generic function expects a Type Paramater.

Second Question: How can you work around not being able to do so?

I ended up doing like @silkfire and @Lee suggested, having a function that takes the type as an argument instead of an generic function. However I still prefer generic functions over casting when using a function so I ended up using two functions.

private static object Function(Type type, Arguments args)
{
    // DO FUNCTION STUFF
}

and

public static T Function<T>(Arguments args)
{
    return (T) Function(typeof(T), args);
}

This way the user can still call the function in a generic way, and by doing so doesn't have to cast the returned object (In my opinion alot cleaner) and I can call the function and pass in a Type. The non-generic function doesn't have to be public because the only time I need to pass the Type using a Type Instance instead of a Type Parameter is when recursively calling the function from within.

1

You can tell the compiler to force T to be the same as someFieldInfo.Field by passing in an expression (which is never used)

public static T Function<T>(Argument arg, Expression<Func<T>> anyField)
{
}

T result = Function(arg, () => someFieldInfo.Field);

But that's at compile-time. Generic types in C# have to be resolved at compile-time.

You wanted to use somefieldInfo.FieldType at run-time. For run-time types you cannot use generics, because you cannot predict what the type will be.

Instead cast the returned object at run-time using Convert.ChangeType.

public static object Function(Argument arg, Type anyFieldType)
{
    object result = ...;

    return Convert.ChangeType(result, anyFieldType);
}

object result = Function(arg, someFieldInfo.FieldType);
  • Thanks for the answer @buffjape. I got one question though. With your approach wouldn't I still have to cast the returned object if I wanted to use it as it's own type like: `ActualType result = (ActualType) Function(arg, someFieldInfo.FieldType)` the function still returns just an object doesn't it? I wanted to use a generic function in the first place to avoid this casting of the returned result. But yes, as mentioned earlier in the thread passing the type as an argument is the only way to do it when getting the type from fieldInfo.FieldType. – Eric Johansson Jun 26 '17 at 17:12
  • Generic types in C# are resolved at compile-time, so unfortunately you would need a different language to do what you want at run-time. –  Jun 27 '17 at 07:47