Могу ли я иметь базовый класс, в котором каждый производный класс имеет собственную копию статического свойства?

У меня есть что-то вроде следующей ситуации ниже:

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

Могу ли я сделать что-то подобное? Как я могу настроить производные классы для достижения этой цели? Спасибо, парни.

РЕДАКТИРОВАТЬ: По сути, у меня есть куча производных классов, каждый из которых имеет свойство, уникальное для этого класса. Он не меняется для каждого экземпляра, и поэтому я считаю, что это должна быть статическая переменная. Кроме того, это свойство задается методом, одинаковым для каждого из этих классов. Я пытаюсь избежать копирования и вставки логики для этого свойства и метода в каждый из этих производных классов. Я подумал, что лучше каким-то образом перенести эту логику в базовый класс, от которого происходят все эти классы. Но мне нужно, чтобы каждый производный класс имел собственную копию этого свойства. Мне не обязательно делать это таким образом, и я буду рад услышать некоторые предложения по улучшению практики, если они у вас есть. Спасибо!


person ntsue    schedule 20.02.2011    source источник


Ответы (4)


Вам нужно будет переопределить и скрыть поле и метод во всех производных типах.

Пример:

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, если только производные классы смогут его видеть.

person Femaref    schedule 20.02.2011
comment
Итак, как лучше всего избежать повторения кода в каждом из моих производных классов? Метод будет одинаковым для каждого из моих производных классов. - person ntsue; 21.02.2011
comment
Пожалуйста, отредактируйте свой вопрос, чтобы показать, чего вы хотите достичь. Таким образом, мы сможем помочь вам больше. - person Femaref; 21.02.2011
comment
Итак, я взял код, который вы дали, и изменил его, добавив частную статическую переменную в DerivedA... и я использую переопределенное свойство, чтобы получить и установить это статическое поле... Это нормально? Или это не лучший способ сделать это? Кажется, он делает то, что я хочу.. спасибо!! - person ntsue; 21.02.2011
comment
Ну, дело в том, чтобы вообще не использовать какое-либо статическое поле — вы должны использовать только свойство отдельно. Дело в том, что вам не нужно добавлять статическое поле каждый раз, когда вы получаете, а просто переопределяете свойство и обрабатываете там свой случай. - person Femaref; 21.02.2011
comment
Если я не использую статическое поле, а просто использую свойство... не будет ли каждый экземпляр DerivedA иметь собственную копию имени? Я хотел, чтобы весь класс поделился копией Name. Простите меня, если я не правильно понимаю... Спасибо! - person ntsue; 21.02.2011
comment
Да, было бы, но в чем проблема? Дело в том, что вы не можете требовать от класса реализации статического поля. Однако вы можете потребовать, чтобы класс реализовал общедоступное или защищенное свойство. Небольшая цена за это желание иметь информацию, требуемую кодом, а не документацией. - person Femaref; 21.02.2011

Ну, да, вы можете, но это вращается вокруг небольшого трюка с дженериками.

Гораздо лучше, если вы исправите свой дизайн, чтобы вам не нужно было это статическое поле или, по крайней мере, не для каждого потомка, но вот:

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, это становится сложным, поэтому я бы не рекомендовал идти по этому пути.

person Lasse V. Karlsen    schedule 20.02.2011
comment
Я решил реализовать этот шаблон для того, что я считаю законным шаблоном. Я приветствую обратную связь. Мое статическое свойство содержит статический список сопоставлений замены токенов. Каждый тип электронной почты имеет свой собственный класс, который наследуется от базового класса. Классы используются при обработке электронных писем — в шаблоне электронной почты есть токены, которые заменяются фактическими значениями во время выполнения. Токены не меняются, поэтому я использую статическое свойство: private static Dictionary‹Regex, string› _TokenReplacementMappings = new Dictionary‹Regex, string›() {...}; - person Vince Horst; 03.04.2014
comment
Я тоже предпочитаю этот метод. - person Tejasvi Hegde; 13.03.2015
comment
Но для многоуровневого наследования необходимо смешивать и сочетать такие методы, как этот и описанный выше. - person Tejasvi Hegde; 13.03.2015
comment
Спасибо за понимание. Я совершенно забыл, что универсальные типы создают новую копию статических полей. Как вы сказали, это может быстро стать сложным, если не позаботиться. - person Alex Essilfie; 20.08.2015

Статический словарь с типом в качестве ключей должен подойти. Я имею в виду избегать логического повторения и разных значений для каждого производного типа, но совместно используемых экземплярами.

public class Base
{
    private static Dictionatry<Type,int> _values;

    public int MyMethod()
    {
        _values[this.GetType()]+=5;
        return _values[this.GetType()];
    }
}
person Marcin Machowski    schedule 14.05.2016

Я обычно реализую специфические вещи подкласса как абстрактное свойство 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; } }
}
person Albin Sunnanbo    schedule 20.02.2011
comment
Ключ (которого здесь нет) заключается в том, что это свойство static. - person neizan; 23.05.2017