Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# generics: any way to refer to the generic parameter types as a collection?

Tags:

c#

.net

generics

I need to write a bunch of methods that take 1..N generic type parameters, eg:

int Foo<T1>();
int Foo<T1,T2>();
int Foo<T1,T2,T3>();
...
int Foo<T1,T2,T3...TN>();

Inside Foo() I would like to do something for each type, eg

int Foo<T1,T2,T3>() {
    this.data = new byte[3]; // allocate 1 array slot per type
}

Is there any way to parameterize this so that I am not editing every variation of Foo(), something analogous to:

int Foo<T1,T2,T3>() {
    this.data = new byte[_NUMBER_OF_GENERIC_PARAMETERS];
}

Ideally, I'd also like to be able to get an array or collection of the types as well:

int Foo<T1,T2,T3>() {
    this.data = new byte[_NUMBER_OF_GENERIC_PARAMETERS];

    // can do this
    Type [] types = new Type[] { T1, T2, T3 };
    // but would rather do this
    Type [] types = _ARRAY_OR_COLLECTION_OF_THE_GENERIC_PARAMETERS;
}
like image 637
CoderBrien Avatar asked Aug 04 '13 16:08

CoderBrien


2 Answers

You can read the current generic parameters and their number from the MethodInfo.GetGenericArguments array.

You can retrieve the MethodInfo for your current method by using the MethodBase.GetCurrentMethod method.

Note that you will still need to supply several generic overloads of your method with different numbers of generic parameters, as C# and the CLI do not support variadic generic parameter lists.

So, your code sample for the method with three generic parameters could be written like this:

int Foo<T1,T2,T3>() {
    MethodInfo mInfo = (MethodInfo)MethodBase.GetCurrentMethod();
    Type[] types = mInfo.GetGenericArguments();

    this.data = new byte[types.Length];
}
like image 112
O. R. Mapper Avatar answered Sep 19 '22 09:09

O. R. Mapper


1) You can get the number of template arguments via reflection: http://msdn.microsoft.com/en-us/library/system.reflection.methodbase.getcurrentmethod.aspx . This way, you can have common implementation for each Foo. In each Foo you can just call:

FooImpl();

The only difference (regarding the "GetCurrentMethod") is that you'll need to get method info of the previous method:

StackTrace stackTrace = new StackTrace();
MethodBase methodBase = stackTrace.GetFrame(1).GetMethod();

2) You could generate all Foo versions at runtime - all would share the same implementation of calling FooImpl only. Some details on generating methods at runtime: Creating a function dynamically at run-time and here: http://msdn.microsoft.com/en-us/library/exczf7b9.aspx

like image 32
BartoszKP Avatar answered Sep 22 '22 09:09

BartoszKP