在C#中使用“params”关键字表示通用参数

时间:2013-03-14 18:19:14

标签: c# generics

今天我在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#中的任何方式完成,如果不是,这是一个愚蠢的想法

6 个答案:

答案 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;对于其余的领域。