gpt4 book ai didi

c# - 在 C# 中使用自由泛型类型参数模拟委托(delegate)

转载 作者:太空狗 更新时间:2023-10-29 18:22:44 25 4
gpt4 key购买 nike

这是一个关于语言设计、模式和语义的难题。请不要因为看不到实用值(value)而拒绝投票。

首先,让我们考虑一下函数及其参数。然后,我们将研究带有参数/参数的函数与带有类型参数/类型参数的泛型类/函数之间的类比。

函数 是具有一些称为“参数”的未指定值的代码块。您提供参数并接收结果。

通用类是具有一些未指定“类型参数”的类。您提供类型参数,然后您可以使用该类 - 调用构造函数或调用静态方法。

泛型函数 非泛型类中的函数具有一些未指定的“类型参数”和一些未指定的“值参数”。您提供类型参数值参数来接收结果。

委托(delegate) 是指向特定函数的指针。当您创建委托(delegate)时,您不指定函数参数,而是稍后提供它们。

问题是 .Net 没有等效于具有未指定通用类型参数的通用函数的委托(delegate)。您不能稍后为类型参数 提供类型值。我们可以想象委托(delegate)不仅有自由的值参数,还有自由的类型参数

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# 中使用免费的泛型类型参数模拟委托(delegate)?

我们如何通过非通用代码将引用/链接传递给具有未知通用参数的通用函数[s]?

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 使用类型参数选择正确的函数,将值参数传递给它并返回接收到的值。

最终解决方案: Emulating delegates with free generic type parameters in C#

最佳答案

我认为您在语言中模拟这一点的方式是不使用委托(delegate)而是使用接口(interface)。非泛型接口(interface)可以包含泛型方法,因此您可以获得具有开放类型参数的委托(delegate)的大部分行为。

这里是将您的示例重新编写成一个有效的 C# 程序(请注意,它仍然需要您定义的工厂类):

public interface IWorker
{
ICollection<T> DoWork<T>(IEnumerable<T> values);
}

public class ListCreationWorker : IWorker
{
public ICollection<T> DoWork<T>(IEnumerable<T> values)
{
return Factory.CreateList<T>(values);
}
}

public class SetCreationWorker : IWorker
{
public ICollection<T> DoWork<T>(IEnumerable<T> values)
{
return Factory.CreateSet<T>(values);
}
}

public static class Program {
public static void Main(string[] args) {
string[] values1 = new string[] { "a", "b", "c" };
int[] values2 = new int[] { 1, 2, 2, 2 };

IWorker listWorker = new ListCreationWorker();
IWorker setWorker = new SetCreationWorker();

ICollection<string> result1 = listWorker.DoWork(values1);
ICollection<int> result2 = listWorker.DoWork(values2); //.Count == 4
ICollection<int> result3 = setWorker.DoWork(values2); //.Count == 2
}
}

public static class Factory
{
public static ICollection<T> CreateSet<T>(IEnumerable<T> values)
{
return new HashSet<T>(values);
}

public static ICollection<T> CreateList<T>(IEnumerable<T> values)
{
return new List<T>(values);
}
}

您仍然可以获得将调用哪个方法的决定与所述方法的执行分开的重要特征。

但是,您不能做的一件事是以通用方式将任何状态存储在 IWorker 实现中。我不确定这有什么用,因为每次都可以使用不同类型的参数调用 DoWork 方法。

关于c# - 在 C# 中使用自由泛型类型参数模拟委托(delegate),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12878864/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com