0

假设我有以下代码。

static class Store<T> {
    public static T A;
    public static T B;
    public static T C;
}

public static class Store {
    public static Value A = new Value(<T>(v) => Store<T>.A = v); //just an example of what I want
    public static Value B = new Value(<T>(v) => Store<T>.B = v); //just an example of what I want
    public static Value C = new Value(SetC<T>);  //just an example of what I want

    public static void SetA<T>(T value) { Store<T>.A = value; }
    public static void SetB<T>(T value) { Store<T>.B = value; }
    public static void SetC<T>(T value) { Store<T>.C = value; }
}

public class Value {
    Action<T><T> _valueChanger; //just an example of what I want
    public Value(Action<T><T> valueChanger) { //just an example of what I want
        _valueChanger = valueChanger;
    }

    public void SetValue<T> (T value) {
        _valueChanger<T>(value); //just an example of what I want
    }
}

我想写Store.A.SetValue(42),以便将值保存到Store<int>.A. 我可以写什么来代替标有“只是我想要的示例”的行来实现这一目标?(我想探索一个不涉及字典或类似内容的解决方案)

重新表述问题: 我想修改类Value(定义一些字段,编写构造函数并编写方法 Value.SetValue(T value) ),然后构造三个不同的 Value (A, B, C) 类型的变量,使得当我调用Store.A.SetValue(42)该值Store<int>.A更改为 42。

类的另一种变体:

static class Holder<T> {
    T Value { get; set; }
}

static class Store2<T> {
    public static Holder<T> A = new Holder<T>();
    public static Holder<T> B = new Holder<T>();
    public static Holder<T> C = new Holder<T>();
}

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<TFree>.C); //just an example of what I want
}

public class Value2 { //Non-generic class!
    Holder{TFree}<TFree> _holder; //just an example of what I want
    public Value(Holder{TFree}<TFree> holder) { //just an example of what I want
        _holder = holder;
    }

    public void SetValue<T> (T value) {
        _holder{T}.Value = value; //just an example of what I want
    }
}

public class Value3 { //Non-generic class! (Another variation)
    Func{TFree}<Holder<TFree>> _holderFactory; //just an example of what I want

    public Value(Func{TFree}<Holder<TFree>> holderFactory) { //just an example of what I want
        _holderFactory = holderFactory;
    }

    public void SetValue<T> (T value) {
        Holder<T> holder = _holderFactory{T}(); //just an example of what I want
        holder.Value = value; 
    }
}

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

4

2 回答 2

0

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

public static class Store<T>
{
    public static readonly T[] Values = new T[3];
    public static T A { get { return Values[0]; } set { Values[0] = value; } }
    public static T B { get { return Values[1]; } set { Values[1] = value; } }
    public static T C { 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>(T value)
    {
        Store<T>.Values[_index] = value;
    }

    public T GetValue<T>()
    {
        return Store<T>.Values[_index];
    }
}

由于 的构造函数Value不知道任何泛型类型参数,因此您不能对特定的Store<T>.


更新

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

Store.A.SetValue(42);
Store.A.SetValue("Douglas Adams");
Store.A.SetValue(new DirectoryInfo(@"C:\"));
Store.A.SetValue(new List<int>());

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

通过使用调试器,您将看到同时存储了四个不同的值A!当然,这是A's存在于四种不同的四种不同Store<T>

于 2012-10-13T23:08:11.270 回答
0

事实证明这个问题是可以解决的。Mike-z 为我提供了一个几乎正确的解决方案来解决委托到泛型方法的问题(在 C# 中使用免费的泛型类型参数模拟委托),我将其修改为一个完整的解决方案:(在 C# 中使用免费的泛型类型参数模拟委托) .

这个问题的解决方案也变得很容易。接口可以包含泛型方法,我们可以使用接口值变量来存储泛型方法的链接,而无需指定具体的类型参数。下面的代码在Store<T>没有修改的情况下使用类,并使用ISetter接口和// ASetter“闭包”来保存对不同泛型成员的引用。该类将引用存储在-typed 变量中,并在类型参数可用时使用链接到的泛型成员。BSetterCSetterValueISetter_setterT

public interface ISetter {
    void SetValue<T>(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>(T value) { Store<T>.A = value; }
    }
    class BSetter : ISetter {
        public void SetValue<T>(T value) { Store<T>.B = value; }
    }
    class CSetter : ISetter {
        public void SetValue<T>(T value) { Store<T>.C = value; }
    }
}

public class Value {
    ISetter _setter;

    public Value(ISetter setter) {
        _setter = setter;
    }

    public void SetValue<T> (T value) {
        _setter.SetValue<T>(value);
    }
}
于 2012-10-19T03:43:20.783 回答