今天我在C#.NET 4.5中遇到了漂亮的Func<T1, T2, T3, T4, T5, T6, T7, T8, T9, T10, T11, T12, T13, T14, T15, T16, TResult>
代表。我假设16是一个任意停止的地方(哪些方法有超过16个参数?)但它让我思考:是否有可能在C#中指定泛型类型可以有任意数量的类型参数?以类似的方式,方法的params关键字允许方法的任意数量的参数。像这样:
public class MyInfiniteGenericType<params T[]> { ... }
然后,您可以在类中通过枚举或使用T[index]
来访问类型参数,方法与params
允许在方法中一样。
我个人从来没有使用它,但Func代表将是一个使用它的完美场所。不需要16种不同类型的Func!
所以我的问题是,这可以用C#中的任何方式完成,如果不是,这是一个愚蠢的想法?
答案 0 :(得分:42)
是否可以在C#中指定泛型类型可以包含任意数量的类型参数?
不,C#没有我喜欢的东西。
就CLR而言,基本上Func<T>
和Func<T1, T2>
是完全不相关的类型,并且没有像params
那样指定多个类型参数。
至于它的实用性:我可以看到它可能有用的情况,但我怀疑它们很少见,意味着该功能没有超过“利益/成本”阈值。 (请注意,它几乎肯定也需要CLR更改。)
答案 1 :(得分:9)
C ++ 11具有您正在谈论的功能。他们称之为variadic templates。
但是,C#泛型并不像C ++模板那样,并且很难构建完全相同的东西。在C ++的情况下,模板在编译时扩展为使用的任何具体类型。在C#案例中,类型规范完全在运行时发生。由此产生的IL需要支持遇到的不同类型的数量。
答案 2 :(得分:1)
不,这不可能。
它并不像将它作为一个类型的数组(在C#中甚至不存在的概念)那样简单。考虑Func
- 类型参数的数量必须与委托的Invoke
方法的参数数量相同。但程序员如何在类型参数和常规参数之间表达这种关系呢?
但是,此功能确实存在于C ++ 11中 - variadic templates。请注意,C ++不允许使用数组语法访问单个类型参数 - 相反,函数通常将第一个类型参数与其余参数分开,并使用递归调用来解包其余参数。
答案 3 :(得分:1)
我发现自己很好奇,看看是否有其他人对此有用。我刚刚编写了一个通用的composer来构建使用Castle Dynamic Proxy组装的mixin的复合材料。
我构建了一个作曲家来支持两个mixin,并且即将继续&#34;复制并粘贴和调整(播放)&#34; 两个mixin作曲家到15个以上的变化17混音作曲家(类似于Func<T>
到Func<T1...T16, T>
)。但后来我想,如果我能定义Composer<TComposer, TIComposite, params[] TIMixin>
那就不好了!
可悲的是,我要复制并粘贴并调整(仿制药帮助我们避免的活动)。
答案 4 :(得分:1)
我遇到了类似的问题。
我需要 params KeyValuePair<Base, Implementation>[] pairs
,其中 Implementation 继承自 Base。
最初,我想到了 IDictionary<Type, Type>
,但这会扼杀泛型在这里的使用。
所以,我所做的是创建一个接口:
public interface IMapping
{
Type Key { get; }
Type Value { get; }
}
及其实现:
public class Mapping<Base, Implementation> : IMapping where Base : class where Implementation : class, Base
{
public Type Key => typeof(Base);
public Type Value => typeof(Implementation);
}
创建方法:
public static void Initialize(params IMapping[] mappings)
{
foreach (var mapping in mappings)
{
//We got our mapping, let's map
}
}
并将其用作:
Initialize(
new Mapping<IMainView, MainView>(),
new Mapping<IDashboardView, DashboardView>()
);
答案 5 :(得分:0)
不,不可能拥有任意数量的通用参数。这可能也是一个愚蠢的想法,因为泛型类型参数在运行时没有被解析,它们在编译时被解析,因此迭代它们就不是一件明显的事情了。
您可能还认为Tuple&lt; ,,,,,,,,&gt;对于它来说可能是一个显而易见的地方,但是当你用完通用参数时,你可以使最后一个成为元组&lt; ,,,,&gt;对于其余的领域。