这是一个关于语言设计、模式和语义的难题。请不要仅仅因为您没有看到实用价值而投反对票。
首先,让我们考虑一下函数及其参数。然后我们将看看函数及其参数/参数和泛型类/函数及其类型参数/类型参数之间的类比。
函数是具有一些未指定值的代码块,称为“参数”。您提供参数并接收结果。
泛型类是具有一些未指定的“类型参数”的类。您提供类型参数,然后您可以使用该类 - 调用构造函数或调用静态方法。
非泛型类中的泛型函数是具有一些未指定的“类型参数”和一些未指定的“值参数”的函数。您提供类型参数和值参数来接收结果。
委托是指向特定函数的指针。创建委托时,您不指定函数参数,而是稍后提供它们。
问题是 .Net 对于具有未指定泛型类型参数的泛型函数没有等效的 Delegates 。以后不能为类型参数提供类型值。我们可以想象委托不仅具有自由值参数,而且还具有自由类型参数。
static class SomeClass {
//generic function
public static T GetValue<T>() {
return default(T);
}
}
//creating delegate to generic function or method group
Func{TFree}<TFree> valueFactory = SomeClass.GetValue;
//creating delegate to anonymous generic function
Func{TFree}<int, List<TFree>> listFactory = {TFree}(int capacity) => new List<TFree>(capacity);
下面是我想用 C# 编写的程序的 [伪] 代码。我想知道如何在正确的 C# 程序中实现类似的行为。
我们如何在 C# 中使用免费的泛型类型参数来模拟委托?
我们如何通过非泛型代码将引用/链接传递给具有未知泛型参数的泛型函数?
public static class Factory { //Everything compiles fine here
public delegate ICollection<T> FactoryDelegate<T>(IEnumerable<T> values);
public static ICollection<T> CreateList<T>(IEnumerable<T> values) {
return new List<T>(values);
}
public static ICollection<T> CreateSet<T>(IEnumerable<T> values) {
return new HashSet<T>(values);
}
}
public class Worker { //non-generic class
Func{TFree}<FactoryDelegate<TFree>> _factory; //TFree is a "free" generic type paramenter
public Worker(Func{TFree}<FactoryDelegate<TFree>> factory) {
_factory = factory;
}
public ICollection<T> DoWork<T>(IEnumerable<T> values) { //generic method
return _factory{T}(values); //supplying T as the argument for type parameter TFree
}
}
public static class Program {
public static void Main() {
string[] values1 = new string[] { "a", "b", "c" };
int[] values2 = new int[] { 1, 2, 2, 2 };
Worker listWorker = new Worker(Factory.CreateList); //passing reference to generic function
Worker setWorker = new Worker(Factory.CreateSet); //passing reference to generic function
ICollection<string> result1 = listWorker.DoWork(values1);
ICollection<int> result2 = listWorker.DoWork(values2); //.Count == 4
ICollection<int> result3 = setWorker.DoWork(values2); //.Count == 2
}
}
看看我们如何在不指定类型参数的情况下将泛型函数(Factory.CreateList 和 Factory.CreateSet)的引用传递给 Worker 类构造函数?稍后在使用具体类型数组调用通用 DoWork 函数时提供类型参数。DoWork 使用类型参数来选择正确的函数,将值参数传递给它并返回接收到的值。
最终解决方案: 在 C# 中使用免费的泛型类型参数模拟委托