为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

PHP
ITMISS 2024-01-21 10:04:50
我希望能够拥有这个通用类: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我读到了这一点,但它是不够的,因为我不想每次需要共享值时都重复代码:在不同的泛型类实例之间共享静态字段我不想为每个泛型类型创建一个基类,也不想为嵌套或包装类创建一个基类:它太费力、太重而且不能分解。我只是希望能够定义几个通用开放类型并在其中放入一些共享静态变量。如何解决这个通用多态性缺陷?
查看完整描述

2 回答

?
隔江千里

TA贡献1906条经验 获得超10个赞

我认为有 3 种方法适合您:

  1. 创建一个包含共享字段的非通用基类

  2. 创建一个包含共享字段的非通用单独类

  3. 创建一个保存这些共享值的非泛型类型,并在泛型类型中重用它

对于第三个,既然你说你并不真正想要选项 1 或 2,那么这里有一个例子:

public abstract class Shared

{

    private readonly static Dictionary<Guid, object> _Variables

        = new Dictionary<Guid, object>();


    protected void SetValue<T>(Guid key, T value)

    {

        lock (_Variables)

            _Variables[key] = value;

    }


    protected T GetValue<T>(Guid key)

    {

        object temp;

        lock (_Variables)

            if (!_Variables.TryGetValue(key, out temp))

                return default;


        return (T)temp;

    }

}


public class Shared<T> : Shared

{

    private readonly Guid _Key;


    public Shared(Guid key)

    {

        _Key = key;

    }


    public T Value

    {

        get => GetValue<T>(_Key);

        set => SetValue<T>(_Key, value);

    }

}

你可以像这样使用它:


public class MyClass<T>

{

    private static readonly Shared<string> _Shared

        = new Shared<string>(Guid.Parse("521ecaba-2a5e-43f2-90e0-fda38a32618c"));


    public void Set(string value)

    {

        _Shared.Value = value;

    }


    public void Get()

    {

        Console.WriteLine(_Shared.Value);

    }

}

该 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

{

    protected static string _Shared;

}


public class MyClass<T> : MyClass

{

    public void Set(string value)

    {

        _Shared = value;

    }


    public void Get()

    {

        Console.WriteLine(_Shared);

    }

}

如果您更喜欢“基类”,即保存共享值的类型,不可用,并且与基类关系不大(也不适用于结构),您可以轻松地将其设为一个完全独立的类:


internal static class MyClassShared

{

    public static string Shared;

}


public class MyClass<T>

{

    public void Set(string value)

    {

        MyClassShared.Shared = value;

    }


    public void Get()

    {

        Console.WriteLine(MyClassShared.Shared);

    }

}


查看完整回答
反对 回复 2024-01-21
?
倚天杖

TA贡献1828条经验 获得超3个赞

这是我的解决方案,源自 @LasseVågsætherKarlsen

使用指南和字典的想法。

它终于起作用了,而且非常简单!

我估计他的解决方案的因式分解和可重用性的优势超过了其他重复代码和性能降低。

现在可以减少代码并且更易于维护。

谢谢。

SharedStaticValue 类

public class SharedStaticValue<T>

{


  static private class Collector

  {

    static private readonly object locker = new object();

    static private readonly Dictionary<Guid, object> _Values

        = new Dictionary<Guid, object>();

    static internal void SetValue<T>(Guid key, T value)

    {

      lock ( locker )

        if ( _Values.ContainsKey(key) )

          _Values[key] = value;

        else

          _Values.Add(key, value);

    }

    static internal T GetValue<T>(Guid key)

    {

      lock ( locker )

        if ( _Values.ContainsKey(key) )

          return (T)_Values[key];

        else

        {

          T value = default(T);

          _Values.Add(key, value);

          return value;

        }

    }

  }


  private readonly Guid ID;


  public T Value

  {

    get { return Collector.GetValue<T>(ID); }

    set { Collector.SetValue(ID, value); }

  }


  public override string ToString()

  {

    return Value.ToString();

  }


  public SharedStaticValue(Guid id)

  {

    ID = id;

  }


}

考试

public class GenericClass<T>

{

  static public int Value

  {

    get { return _Value.Value; }

    set { _Value.Value = value; }

  }

  static private SharedStaticValue<int> _Value

    = new SharedStaticValue<int>(Guid.Parse("521ecaba-2a5e-43f2-90e0-fda38a32618c"));

}


internal class Class1 : GenericClass<int>

{

}


internal class Class2 : GenericClass<string>

{

}


internal class SharedStaticValueTest

{

  private SharedStaticValue<int> value 

    = new SharedStaticValue<int>(Guid.Parse("{E838689A-3B2C-4BFB-A15C-2F1B5D65F1DE}"));

  public void RunTest()

  {

    Action<string> write = (str) =>

    {

      Console.WriteLine(str);

      Console.WriteLine("  this.SharedStaticValue<int> = " + value.Value);

      Console.WriteLine("  GenericClass<double> = " + GenericClass<double>.Value);

      Console.WriteLine("  GenericClass<int> = " + GenericClass<int>.Value);

      Console.WriteLine("  Class1 extend GenericClass<int> = " + Class1.Value);

      Console.WriteLine("  Class2 extend GenericClass<string> = " + Class2.Value);

      Console.WriteLine();

    };

    write("Default values");

    value.Value = 10;

    write("Set this.SharedStaticValue<int>.Value = 10");

    GenericClass<double>.Value = 20;

    write("Set GenericClass<double>.Value = 20");

    GenericClass<int>.Value = 30;

    write("Set GenericClass<int>.Value = 30");

    Class1.Value = 40;

    write("Set Class1 extend GenericClass<int>.Value = 40");

    Class2.Value = 50;

    write("Set Class2 extend GenericClass<string>.Value = 50");

  }

}

输出

Default values

  this.SharedStaticValue<int> = 0

  GenericClass<double> = 0

  GenericClass<int> = 0

  Class1 extend GenericClass<int> = 0

  Class2 extend GenericClass<string> = 0


Set this.SharedStaticValue<int>.Value = 10

  this.SharedStaticValue<int> = 10

  GenericClass<double> = 0

  GenericClass<int> = 0

  Class1 extend GenericClass<int> = 0

  Class2 extend GenericClass<string> = 0


Set GenericClass<double>.Value = 20

  this.SharedStaticValue<int> = 10

  GenericClass<double> = 20

  GenericClass<int> = 20

  Class1 extend GenericClass<int> = 20

  Class2 extend GenericClass<string> = 20


Set GenericClass<int>.Value = 30

  this.SharedStaticValue<int> = 10

  GenericClass<double> = 30

  GenericClass<int> = 30

  Class1 extend GenericClass<int> = 30

  Class2 extend GenericClass<string> = 30


Set Class1 extend GenericClass<int>.Value = 40

  this.SharedStaticValue<int> = 10

  GenericClass<double> = 40

  GenericClass<int> = 40

  Class1 extend GenericClass<int> = 40

  Class2 extend GenericClass<string> = 40


Set Class2 extend GenericClass<string>.Value = 50

  this.SharedStaticValue<int> = 10

  GenericClass<double> = 50

  GenericClass<int> = 50

  Class1 extend GenericClass<int> = 50

  Class2 extend GenericClass<string> = 50


查看完整回答
反对 回复 2024-01-21
  • 2 回答
  • 0 关注
  • 109 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信