使用"params"c#中用于通用参数的关键字

本文关键字:quot 参数 关键字 params 使用 用于 | 更新日期: 2023-09-27 18:03:51

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

使用"params"c#中用于通用参数的关键字

在c#中是否可以指定泛型类型可以有任意数量的类型参数?

不,c#恐怕没有这样的东西。

就CLR而言,Func<T>Func<T1, T2>基本上是完全不相关的类型,并且不像params那样指定多个类型参数。

至于它的效用:我可以看到它可能有用的情况,但我怀疑它们足够罕见,意味着该功能不会超过"收益/成本"阈值。(请注意,它几乎肯定也需要更改CLR)

c++ 11具有您所谈论的特性。他们称之为可变模板。

c#泛型不太像c++模板,但是会使构建完全相同的东西变得困难。

在c++的情况下,模板在编译时被扩展为所使用的具体类型。在c#的情况下,类型规范完全发生在运行时。生成的IL需要支持遇到的不同类型的数量。

不,这是不可能的。

这并不像把它当作一个类型数组(c#中甚至不存在这个概念)那么简单。考虑Func—类型参数的数量必须与委托的Invoke方法的参数数量相同。但是程序员如何表达类型参数和常规参数之间的这种关系呢?

然而,这个特性在c++ 11可变模板中确实存在。请注意,c++不允许使用数组语法访问单个类型参数——相反,函数通常将第一个类型参数与其他类型参数分开,并使用递归调用来解包其余的类型参数。

我只是觉得自己很好奇,想看看其他人是否有这个用途。我刚刚写了一个通用的编写器,从使用Castle动态代理组装的mixins中构建复合。

我建立了作曲家来支持两个混音,并准备继续;复制和粘贴和调整(bleh)&;两个混音作曲家到15个更多的变化到17个混音作曲家(类似于Func<T>Func<T1...T16, T>)。但后来我想,如果我能定义Composer<TComposer, TIComposite, params TIMixin[]>不是很好吗!

遗憾的是,我要去复制粘贴和调整了(这正是泛型帮助我们避免的活动)。

我也有类似的问题。我需要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>()
);

不可以,不能有任意数量的泛型参数。这可能也是一个愚蠢的想法,因为泛型类型参数不是在运行时解析的,而是在编译时解析的,所以像这样迭代它们根本不是一件明显的事情。

您可能还认为Tuple<,,,,,,,,>可能是放置它的明显位置,但解决方案是,当您用完泛型参数时,将最后一个字段设置为Tuple<,,,,>,用于其余字段。

我不知道这是否有用,但一个变通方法可能是:

Func<List<object>>

您必须手动将每个元素转换为各自的数据类型。您可以迭代地使用它:

 Convert.ChangeType(obj, obj.GetType())//using System;

你可以有一组你想要的变量