[英]C# generics: any way to refer to the generic parameter types as a collection?
我需要编写一堆采用1..N泛型类型参数的方法,例如:
int Foo<T1>();
int Foo<T1,T2>();
int Foo<T1,T2,T3>();
...
int Foo<T1,T2,T3...TN>();
在Foo()
里面,我想为每种类型做一些事情,例如
int Foo<T1,T2,T3>() {
this.data = new byte[3]; // allocate 1 array slot per type
}
有没有办法参数化这个,所以我不编辑Foo()
每个变体,类似于:
int Foo<T1,T2,T3>() {
this.data = new byte[_NUMBER_OF_GENERIC_PARAMETERS];
}
理想情况下,我也希望能够获得一个数组或类型的集合:
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;
}
您可以从MethodInfo.GetGenericArguments
数组中读取当前通用参数及其编号。
您可以使用MethodBase.GetCurrentMethod
方法检索当前方法的MethodInfo
。
请注意,由于C#和CLI不支持可变参数通用参数列表,因此仍需要使用不同数量的通用参数提供方法的几个泛型重载。
因此,具有三个通用参数的方法的代码示例可以这样写:
int Foo<T1,T2,T3>() {
MethodInfo mInfo = (MethodInfo)MethodBase.GetCurrentMethod();
Type[] types = mInfo.GetGenericArguments();
this.data = new byte[types.Length];
}
1)您可以通过反射获取模板参数的数量: http : //msdn.microsoft.com/en-us/library/system.reflection.methodbase.getcurrentmethod.aspx 。 这样,您就可以为每个Foo实现通用实现。 在每个Foo中你可以打电话:
FooImpl();
唯一的区别(关于“GetCurrentMethod”)是你需要获取前一个方法的方法信息:
StackTrace stackTrace = new StackTrace();
MethodBase methodBase = stackTrace.GetFrame(1).GetMethod();
2)您可以在运行时生成所有Foo版本 - 所有版本都将共享调用FooImpl的相同实现。 有关在运行时生成方法的一些细节:在运行时动态创建函数 ,请访问: http : //msdn.microsoft.com/en-us/library/exczf7b9.aspx
.NET框架将具有N类型参数的泛型类或方法视为具有与具有更多或更少的名称不同的名称。 如果没有对框架进行大的改动就可以安排事情以便调用函数
foo<T>(autogeneric ref T it)
如:
foo(1, "George", 5.7);
将被翻译为:
struct foo99 {public int p1; public string p2; public double p3};
...
foo99 temp99;
temp99.p1 = 1;
temp99.p2 = "George";
temp99.p3 = 5.7;
foo1(ref temp);
这将允许通用方法有效地接受任意数量的参数。 能够通过ref传递这样的匿名结构可能看起来并不十分有用,但是当与lambdas结合使用时它可能非常强大。
通常,关闭lambda表达式中的局部变量需要将局部变量提升到堆对象并构建一个以该堆对象为目标的委托。 如果可以使用上述样式,则可以代替创建持久闭包对象和委托并传递委托,只需将适当的变量提升到结构并将一个byref与静态委托一起传递给它。 这只适用于被调用的例程不必持久传递闭包的情况,但在另一方面,调用者会知道被调用的例程不会持久化闭包。 此外,虽然没有.NET语言会支持这样的事情,并且可能需要进行一些框架更改以允许执行此操作的代码是易变的,通过引用传递一个结构,其中一些成员也是byrefs可以使lambda可以访问封闭过程的ref
参数 - 目前不可能的(因为不能保证创建的委托不会比创建它的范围更长)。 结构在它们所处的范围死亡时死亡,因此问题不一定存在。
我希望.NET语言有一种表达这些概念的便捷方式。 闭包可以导致变量的生命周期被任意持久化的事实意味着在闭包中曾经使用过变量的代码必须假设外部代码可以随时改变它。 基于结构的方法不会有这个问题。
不能。您不能根据需要使用Type参数。 但你可以使用像Tuple这样的东西。 它允许你包装泛型。 但是你不能使用TypeParamter本身。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.