【问题标题】:Can I have a base class where each derived class has its own copy of a static property?我可以有一个基类,其中每个派生类都有自己的静态属性副本吗?
【发布时间】:2011-06-30 21:57:20
【问题描述】:

我有类似以下情况:

class Base
{
     public static int x;
     public int myMethod()
     {
          x += 5;
          return x;
     }

}

class DerivedA : Base
{
}

class DerivedB : Base
{
}

我正在尝试进行设置,以便每个派生类都有自己的 x 静态实例,如果我执行以下操作:

 DerivedA.x = 5;
 DerivedB.x = 10;

然后当我跑步时:

 DerivedA.myMethod(); //The result will be 10
 DerivedB.myMethod(); //The reusult will be 15

我可以这样做吗?如何设置派生类来实现这一点?谢谢各位。

编辑:基本上,我有一堆派生类,每个派生类都有该类独有的属性。它不会因每个实例而变化,因此我认为应该是一个静态变量。此外,该属性是由一个方法设置的,对于这些类中的每一个都是相同的。 我试图避免在每个派生类中复制和粘贴该属性和方法的逻辑。我认为最好以某种方式将该逻辑移至派生这些类中的每一个的基类。但是,我需要每个派生类都有自己的该属性的副本。 我不一定必须这样做,如果你们有任何更好的做法建议,我会很高兴听到.. 谢谢!

【问题讨论】:

    标签: c# inheritance derived-class base-class


    【解决方案1】:

    以 Type 作为键的静态字典应该这样做。我的意思是避免逻辑重复和每个派生类型的不同值,但在实例之间共享。

    public class Base
    {
        private static Dictionatry<Type,int> _values;
    
        public int MyMethod()
        {
            _values[this.GetType()]+=5;
            return _values[this.GetType()];
        }
    }
    

    【讨论】:

      【解决方案2】:

      您将需要重新定义和隐藏所有派生类型中的字段和方法。

      例子:

      class DerivedA : Base
      {
        public new static int x;
        public new int myMethod()
        {
          x += 5;
          return x;
        }
      }
      

      注意:不要这样做。修正你的设计。

      编辑:

      实际上,我也有类似的结构。我用一个抽象(如果你需要一个默认值,使用virtual)属性来解决它,然后从基类中使用它:

      public abstract class Base
      {
         public abstract string Name { get; }
      
         public void Refresh()
         {
           //do something with Name
         }
      }
      
      public class DerivedA
      {
        public override string Name { get { return "Overview"; } }
      }
      

      您应该能够针对您的用例进行调整。如果只有派生类应该能够看到它,您当然可以将属性设置为 protected

      【讨论】:

      • 那么,避免在每个派生类中重复代码的最佳方法是什么?对于我的每个派生类,该方法都是相同的。
      • 请编辑您的问题以显示您想要实现的目标。我们将能够通过这种方式为您提供更多帮助。
      • 所以,我获取了您提供的代码,并通过向 DerivedA 添加了一个私有静态变量来修改它...我使用覆盖的属性来获取和设置该静态字段...可以吗?或者这不是一个好方法吗?它似乎做我想要的......谢谢!
      • 嗯,关键是不要使用任何静态字段——你应该只使用它自己的属性。关键是您不必每次派生时都添加静态字段,而只需覆盖该属性并在那里处理您的情况。
      • 如果我不使用静态字段,而只使用属性.. 不是每个 DerivedA 实例都有自己的“名称”副本吗?我希望全班都分享“姓名”的副本。如果我没有正确理解,请原谅我......谢谢!
      【解决方案3】:

      我通常将子类特定的东西实现为抽象的 get 属性

      public class Base
      {
          // You must pick one option below
      
          // if you have a default value in the base class
          public virtual int x { get { return 7; /* magic default value */} }
      
          // if you don't have a default value
          // if you choose this alternative you must also make the Base class abstract
          public abstract int x { get; }
      }
      
      public class DerivedA : Base
      {
          public override int x { get { return 5; } }
      }
      
      public class DerivedB : Base
      {
          public override int x { get { return 10; } }
      }
      

      【讨论】:

      • 关键(这里缺少的)是属性是static
      【解决方案4】:

      嗯,是的,你可以,但它围绕着一个与泛型有关的技巧。

      如果你修复你的设计,这样你就不需要那个静态字段,或者至少不需要每个后代,那就更好了,但是这里是:

      class Base<TDescendant>
          where TDescendant : Base
      {
           public static int x;
           public int myMethod()
           {
                x += 5;
                return x;
           }
      
      }
      
      class DerivedA : Base<DerivedA>
      {
      }
      
      class DerivedB : Base<DerivedB>
      {
      }
      

      这依赖于这样一个事实,即具有静态字段的泛型类型将为您调用它的每种类型获得这些静态字段的单独副本。

      但是,如果您打算从 DerivedA 或 DerivedB 下降,就会变得棘手,因此我不建议您走这条路。

      【讨论】:

      • 我选择实现这个模式是因为我认为这是一个合法的模式。我欢迎反馈。我的静态属性是一个包含令牌替换映射的静态列表的属性。每种电子邮件类型都有自己的类,该类继承自一个基类。这些类用于处理电子邮件 - 电子邮件模板中有标记,这些标记在运行时替换为实际值。令牌不会改变,所以我使用静态属性: private static Dictionary _TokenReplacementMappings = new Dictionary() {...};
      • 我也喜欢这种方法。
      • 但是对于多级继承,需要和上面这样的技术混合搭配。
      • 感谢您的洞察力。我完全忘记了泛型类型会创建静态字段的新副本。就像你说的那样,如果不小心,这很快就会变得棘手。
      猜你喜欢
      • 2011-07-17
      • 1970-01-01
      • 2018-07-13
      • 1970-01-01
      • 2016-03-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多