使用"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#中以任何方式完成,如果不能,这是一个愚蠢的想法?
在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;
你可以有一组你想要的变量