委托通用类型未知的通用操作。 如何创造这样的东西?

假设我有以下代码。

static class Store { public static TA; public static TB; public static TC; } public static class Store { public static Value A = new Value((v) => Store.A = v); //just an example of what I want public static Value B = new Value((v) => Store.B = v); //just an example of what I want public static Value C = new Value(SetC); //just an example of what I want public static void SetA(T value) { Store.A = value; } public static void SetB(T value) { Store.B = value; } public static void SetC(T value) { Store.C = value; } } public class Value { Action _valueChanger; //just an example of what I want public Value(Action valueChanger) { //just an example of what I want _valueChanger = valueChanger; } public void SetValue (T value) { _valueChanger(value); //just an example of what I want } } 

我想编写Store.A.SetValue(42)以便将值保存到Store.A 。 我可以写什么而不是用“仅仅是我想要的一个例子”标记的线来实现这一点? (我想探索一个不涉及字典或类似内容的解决方案)

解释问题:我想修改类Value (定义一些字段,编写构造函数并编写方法Value.SetValue(T value)),然后以这种方式构造Value(A,B,C)类型的三个不同变量当我调用Store.A.SetValue(42) ,值Store.A更改为42。

课程的另一种变化:

 static class Holder { T Value { get; set; } } static class Store2 { public static Holder A = new Holder(); public static Holder B = new Holder(); public static Holder C = new Holder(); } public static class Store2 { public static Value A = new Value2(Store2.A); //just an example of what I want public static Value B = new Value2(Store2.B); //passing non-specific generic expression public static Value C = new Value3({TFree}() => Store2.C); //just an example of what I want } public class Value2 { //Non-generic class! Holder{TFree} _holder; //just an example of what I want public Value(Holder{TFree} holder) { //just an example of what I want _holder = holder; } public void SetValue (T value) { _holder{T}.Value = value; //just an example of what I want } } public class Value3 { //Non-generic class! (Another variation) Func{TFree}<Holder> _holderFactory; //just an example of what I want public Value(Func{TFree}<Holder> holderFactory) { //just an example of what I want _holderFactory = holderFactory; } public void SetValue (T value) { Holder holder = _holderFactory{T}(); //just an example of what I want holder.Value = value; } } 

解决方案:使用另一个问题的答案( 使用C#中的 免费generics类型参数模拟委托和使用 C#中的免费generics类型参数模拟委托),找到了一个简单的无reflection和无集合的解决方案。 解决方案是委托给generics操作,其中generics类型是未知的。 如何创造这样的东西? 。

使用数组存储值并使用索引通过属性访问它们

 public static class Store { public static readonly T[] Values = new T[3]; public static TA { get { return Values[0]; } set { Values[0] = value; } } public static TB { get { return Values[1]; } set { Values[1] = value; } } public static TC { get { return Values[2]; } set { Values[2] = value; } } } public static class Store { public static readonly Value A = new Value(0); public static readonly Value B = new Value(1); public static readonly Value C = new Value(2); } public class Value { private int _index; public Value(int index) { _index = index; } public void SetValue(T value) { Store.Values[_index] = value; } public T GetValue() { return Store.Values[_index]; } } 

由于Value的构造函数不知道任何generics类型参数,因此您不能对特定的Store进行任何引用。


UPDATE

请注意,将为您为T提供的每个不同类型参数创建Store的副本。 看这个例子

 Store.A.SetValue(42); Store.A.SetValue("Douglas Adams"); Store.A.SetValue(new DirectoryInfo(@"C:\")); Store.A.SetValue(new List()); var x1 = Store.A.GetValue(); // --> 42 var x2 = Store.A.GetValue(); // --> "Douglas Adams" var x3 = Store.A.GetValue(); // --> DirectoryInfo{ C:\ } var x4 = Store.A.GetValue>(); // --> List{ Count = 0 } 

通过使用调试器,您将看到四个不同的值同时存储在A中! 这是因为这四个不同的A's存在于四个不同的Store

问题结果certificate是可以解决的。 Mike-z为我提供了一个几乎正确的委托 – 通用方法问题解决方案( 在C#中模拟具有免费generics类型参数的代理 ),我将其修改为一个完整的解决方案:( 在C#中使用免费generics类型参数模拟委托 ) 。

解决这个问题也变得容易了。 接口可以包含generics方法,我们可以使用接口值变量来存储generics方法的链接,而无需指定具体的类型参数。 以下代码使用Store类而不进行修改,并使用ISetter接口和ASetter / BSetter / CSetter “闭包”来保存对不同通用成员的引用。 Value类将引用存储在ISetter -typed变量中,并使用类型参数T变为可用时_setter链接到的generics成员。

 public interface ISetter { void SetValue(T value); } public static class Store { public static Value A = new Value(new ASetter()); public static Value B = new Value(new BSetter()); public static Value C = new Value(new CSetter()); class ASetter : ISetter { public void SetValue(T value) { Store.A = value; } } class BSetter : ISetter { public void SetValue(T value) { Store.B = value; } } class CSetter : ISetter { public void SetValue(T value) { Store.C = value; } } } public class Value { ISetter _setter; public Value(ISetter setter) { _setter = setter; } public void SetValue (T value) { _setter.SetValue(value); } }