如何创建在封闭构造泛型类型的实例之间共享的静态变量?

我希望能够拥有这个通用类:


public class MyClass<T>

{

  static public string SharedString;

}

其中SharedString将是一个静态值,对于封闭构造类型的所有实例都具有相同的值。


因此这些实例:


var instanceInt = new MyClass<int>();

var instanceString = new MyClass<string>();

字段将具有相同的值SharedString。


例如,如果我写:


instanceInt.SharedString = "Text 1";

instanceString.SharedString = "Text 2";

那我想要那个instanceInt.SharedString == "Text 2"。


在 C# 中,SharedString所有 的实例具有相同的值,但与的实例MyClass<int>不同。SharedStringMyClass<string>


所以instanceInt.SharedString == "Text 1"。


我希望能够重用这个概念来创建任何具有任何真正的通用静态字段的类,该字段可以是aspublic或。privateinternal


我读到了这一点,但它是不够的,因为我不想每次需要共享值时都重复代码:

在不同的泛型类实例之间共享静态字段

我不想为每个泛型类型创建一个基类,也不想为嵌套或包装类创建一个基类:它太费力、太重而且不能分解。我只是希望能够定义几个通用开放类型并在其中放入一些共享静态变量。


如何解决这个通用多态性缺陷?


ITMISS
浏览 125回答 2
2回答

隔江千里

我认为有 3 种方法适合您:创建一个包含共享字段的非通用基类创建一个包含共享字段的非通用单独类创建一个保存这些共享值的非泛型类型,并在泛型类型中重用它对于第三个,既然你说你并不真正想要选项 1 或 2,那么这里有一个例子:public abstract class Shared{&nbsp; &nbsp; private readonly static Dictionary<Guid, object> _Variables&nbsp; &nbsp; &nbsp; &nbsp; = new Dictionary<Guid, object>();&nbsp; &nbsp; protected void SetValue<T>(Guid key, T value)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; lock (_Variables)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _Variables[key] = value;&nbsp; &nbsp; }&nbsp; &nbsp; protected T GetValue<T>(Guid key)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; object temp;&nbsp; &nbsp; &nbsp; &nbsp; lock (_Variables)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (!_Variables.TryGetValue(key, out temp))&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return default;&nbsp; &nbsp; &nbsp; &nbsp; return (T)temp;&nbsp; &nbsp; }}public class Shared<T> : Shared{&nbsp; &nbsp; private readonly Guid _Key;&nbsp; &nbsp; public Shared(Guid key)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; _Key = key;&nbsp; &nbsp; }&nbsp; &nbsp; public T Value&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; get => GetValue<T>(_Key);&nbsp; &nbsp; &nbsp; &nbsp; set => SetValue<T>(_Key, value);&nbsp; &nbsp; }}你可以像这样使用它:public class MyClass<T>{&nbsp; &nbsp; private static readonly Shared<string> _Shared&nbsp; &nbsp; &nbsp; &nbsp; = new Shared<string>(Guid.Parse("521ecaba-2a5e-43f2-90e0-fda38a32618c"));&nbsp; &nbsp; public void Set(string value)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; _Shared.Value = value;&nbsp; &nbsp; }&nbsp; &nbsp; public void Get()&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; Console.WriteLine(_Shared.Value);&nbsp; &nbsp; }}该 MyClass 的 Set/Get 方法用于测试通过一种封闭类型设置的值是否可通过另一种封闭类型使用,如下所示:var mc1 = new MyClass<int>();var mc2 = new MyClass<string>();mc1.Set("Test");mc2.Get();这将输出Test.尽管所有封闭类型MyClass<T>都有自己的静态Shared<T>实例,但该实例中包含的值将由共享字典支持,该字典在使用该Shared<T>类型的所有类型之间共享。就我个人而言,我建议使用静态非泛型基类:public abstract class MyClass{&nbsp; &nbsp; protected static string _Shared;}public class MyClass<T> : MyClass{&nbsp; &nbsp; public void Set(string value)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; _Shared = value;&nbsp; &nbsp; }&nbsp; &nbsp; public void Get()&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; Console.WriteLine(_Shared);&nbsp; &nbsp; }}如果您更喜欢“基类”,即保存共享值的类型,不可用,并且与基类关系不大(也不适用于结构),您可以轻松地将其设为一个完全独立的类:internal static class MyClassShared{&nbsp; &nbsp; public static string Shared;}public class MyClass<T>{&nbsp; &nbsp; public void Set(string value)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; MyClassShared.Shared = value;&nbsp; &nbsp; }&nbsp; &nbsp; public void Get()&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; Console.WriteLine(MyClassShared.Shared);&nbsp; &nbsp; }}

倚天杖

这是我的解决方案,源自 @LasseVågsætherKarlsen使用指南和字典的想法。它终于起作用了,而且非常简单!我估计他的解决方案的因式分解和可重用性的优势超过了其他重复代码和性能降低。现在可以减少代码并且更易于维护。谢谢。SharedStaticValue 类public class SharedStaticValue<T>{&nbsp; static private class Collector&nbsp; {&nbsp; &nbsp; static private readonly object locker = new object();&nbsp; &nbsp; static private readonly Dictionary<Guid, object> _Values&nbsp; &nbsp; &nbsp; &nbsp; = new Dictionary<Guid, object>();&nbsp; &nbsp; static internal void SetValue<T>(Guid key, T value)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; lock ( locker )&nbsp; &nbsp; &nbsp; &nbsp; if ( _Values.ContainsKey(key) )&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _Values[key] = value;&nbsp; &nbsp; &nbsp; &nbsp; else&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _Values.Add(key, value);&nbsp; &nbsp; }&nbsp; &nbsp; static internal T GetValue<T>(Guid key)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; lock ( locker )&nbsp; &nbsp; &nbsp; &nbsp; if ( _Values.ContainsKey(key) )&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return (T)_Values[key];&nbsp; &nbsp; &nbsp; &nbsp; else&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; T value = default(T);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; _Values.Add(key, value);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return value;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; }&nbsp; private readonly Guid ID;&nbsp; public T Value&nbsp; {&nbsp; &nbsp; get { return Collector.GetValue<T>(ID); }&nbsp; &nbsp; set { Collector.SetValue(ID, value); }&nbsp; }&nbsp; public override string ToString()&nbsp; {&nbsp; &nbsp; return Value.ToString();&nbsp; }&nbsp; public SharedStaticValue(Guid id)&nbsp; {&nbsp; &nbsp; ID = id;&nbsp; }}考试public class GenericClass<T>{&nbsp; static public int Value&nbsp; {&nbsp; &nbsp; get { return _Value.Value; }&nbsp; &nbsp; set { _Value.Value = value; }&nbsp; }&nbsp; static private SharedStaticValue<int> _Value&nbsp; &nbsp; = new SharedStaticValue<int>(Guid.Parse("521ecaba-2a5e-43f2-90e0-fda38a32618c"));}internal class Class1 : GenericClass<int>{}internal class Class2 : GenericClass<string>{}internal class SharedStaticValueTest{&nbsp; private SharedStaticValue<int> value&nbsp;&nbsp; &nbsp; = new SharedStaticValue<int>(Guid.Parse("{E838689A-3B2C-4BFB-A15C-2F1B5D65F1DE}"));&nbsp; public void RunTest()&nbsp; {&nbsp; &nbsp; Action<string> write = (str) =>&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; Console.WriteLine(str);&nbsp; &nbsp; &nbsp; Console.WriteLine("&nbsp; this.SharedStaticValue<int> = " + value.Value);&nbsp; &nbsp; &nbsp; Console.WriteLine("&nbsp; GenericClass<double> = " + GenericClass<double>.Value);&nbsp; &nbsp; &nbsp; Console.WriteLine("&nbsp; GenericClass<int> = " + GenericClass<int>.Value);&nbsp; &nbsp; &nbsp; Console.WriteLine("&nbsp; Class1 extend GenericClass<int> = " + Class1.Value);&nbsp; &nbsp; &nbsp; Console.WriteLine("&nbsp; Class2 extend GenericClass<string> = " + Class2.Value);&nbsp; &nbsp; &nbsp; Console.WriteLine();&nbsp; &nbsp; };&nbsp; &nbsp; write("Default values");&nbsp; &nbsp; value.Value = 10;&nbsp; &nbsp; write("Set this.SharedStaticValue<int>.Value = 10");&nbsp; &nbsp; GenericClass<double>.Value = 20;&nbsp; &nbsp; write("Set GenericClass<double>.Value = 20");&nbsp; &nbsp; GenericClass<int>.Value = 30;&nbsp; &nbsp; write("Set GenericClass<int>.Value = 30");&nbsp; &nbsp; Class1.Value = 40;&nbsp; &nbsp; write("Set Class1 extend GenericClass<int>.Value = 40");&nbsp; &nbsp; Class2.Value = 50;&nbsp; &nbsp; write("Set Class2 extend GenericClass<string>.Value = 50");&nbsp; }}输出Default values&nbsp; this.SharedStaticValue<int> = 0&nbsp; GenericClass<double> = 0&nbsp; GenericClass<int> = 0&nbsp; Class1 extend GenericClass<int> = 0&nbsp; Class2 extend GenericClass<string> = 0Set this.SharedStaticValue<int>.Value = 10&nbsp; this.SharedStaticValue<int> = 10&nbsp; GenericClass<double> = 0&nbsp; GenericClass<int> = 0&nbsp; Class1 extend GenericClass<int> = 0&nbsp; Class2 extend GenericClass<string> = 0Set GenericClass<double>.Value = 20&nbsp; this.SharedStaticValue<int> = 10&nbsp; GenericClass<double> = 20&nbsp; GenericClass<int> = 20&nbsp; Class1 extend GenericClass<int> = 20&nbsp; Class2 extend GenericClass<string> = 20Set GenericClass<int>.Value = 30&nbsp; this.SharedStaticValue<int> = 10&nbsp; GenericClass<double> = 30&nbsp; GenericClass<int> = 30&nbsp; Class1 extend GenericClass<int> = 30&nbsp; Class2 extend GenericClass<string> = 30Set Class1 extend GenericClass<int>.Value = 40&nbsp; this.SharedStaticValue<int> = 10&nbsp; GenericClass<double> = 40&nbsp; GenericClass<int> = 40&nbsp; Class1 extend GenericClass<int> = 40&nbsp; Class2 extend GenericClass<string> = 40Set Class2 extend GenericClass<string>.Value = 50&nbsp; this.SharedStaticValue<int> = 10&nbsp; GenericClass<double> = 50&nbsp; GenericClass<int> = 50&nbsp; Class1 extend GenericClass<int> = 50&nbsp; Class2 extend GenericClass<string> = 50
打开App,查看更多内容
随时随地看视频慕课网APP