Получение статических членов - PullRequest
3 голосов
/ 05 декабря 2008

У меня есть базовый класс с закрытым статическим членом:

class Base
{
    private static Base m_instance = new Base();
    public static Base Instance
    {
        get { return m_instance; }
    }
}

И я хочу извлечь несколько классов из этого:

class DerivedA : Base {}
class DerivedB : Base {}
class DerivedC : Base {}

Однако в этот момент вызов DerivedA :: Instance вернет тот же объект, что и DerivedB :: Instance и DerivedC :: Instance. Я могу решить эту проблему, объявив экземпляр в производном классе, но тогда каждый отдельный производный класс должен будет это сделать, и это просто кажется ненужным. Так есть ли способ поместить все это в базовый класс? Можно ли применить шаблон дизайна?

Ответы [ 3 ]

11 голосов
/ 05 декабря 2008

Есть один очень странный способ сделать это:

class Base
{
     // Put common stuff in here...
}

class Base<T> : Base where T : Base<T>, new()
{
    private static T m_instance = new T();

    public static T Instance { get { return m_instance; } }
}

class DerivedA : Base<DerivedA> {}
class DerivedB : Base<DerivedB> {}
class DerivedC : Base<DerivedC> {}

Это работает, потому что есть одна статическая переменная на составной тип - например, List<string> отличается от List<int> и поэтому имеет отдельные статические переменные.

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

В общем, это неприятная вещь. Статические переменные на самом деле не предназначены для такого использования - я только что использовал функцию обобщений, чтобы получить «своего рода» поведение, о котором вы просили.

Также обратите внимание, что Base<DerivedA>.Instance вернет тот же результат, что и DerivedA.Instance - свойство / переменная не "знает", что вы используете DerivedA.Instance. Я не знаю, важно ли это для тебя.

С помощью дополнительного неуниверсального класса вы можете написать:

Base t = DerivedA.Instance;
t = DerivedB.Instance;

Если вам это не нужно, выньте его:)

6 голосов
/ 05 декабря 2008

Статические методы не поддерживают полиморфизм, поэтому такая вещь невозможна.

По сути, свойство Instance не имеет представления о том, как вы его используете. И единственная реализация этого будет существовать, поскольку это статично. Если вы действительно хотели это сделать, доступно это «не рекомендуемое» решение (идея пришла от решения Джона):

private static Dictionary<Type, Base> instances = new Dictionary<Type, Base>();
public static T GetInstance<T>() where T : Base, new() {
  Type ty = typeof(T);
  T x;
  if (instances.TryGetValue(ty, out x)) return x;
  x = new T();
  instances[ty] = x;
  return x;
}
3 голосов
/ 05 декабря 2008

Краткий ответ: не то, что я знаю. Статические члены всегда не виртуальны и не поддерживают полиморфизм.

Однако вы должны также спросить себя почему вы это делаете. Как правило, статические члены являются общими ресурсами, которые каждый экземпляр этого класса (включая производные классы) сочтет полезными. Однако, когда вы создаете статический экземпляр, вы обычно строите в направлении одноэлементного шаблона. В этом случае вы обычно хотите запечатать класс, чтобы у вас не было производных классов, таким образом, рендеринг целиком был полностью спорен Таким образом, вам действительно следует проанализировать, почему вы хотите это сделать, и вместо этого решить эту проблему.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...