Подтвердить что ты не робот

С#, реализовать "статические абстрактные" методы

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

Например, у меня есть абстрактный класс, который имеет строку описания. Поскольку эта строка является общей для всех экземпляров, она помечена как статическая, но я хочу, чтобы все классы, полученные из этого класса, предоставляли свое собственное свойство Description, поэтому я обозначил его как абстрактный:

abstract class AbstractBase
{
    ...
    public static abstract string Description{get;}
    ...
}

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

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

Любые идеи?

4b9b3361

Ответ 1

Объединение статичных и абстрактных несколько бессмысленно, да. Идея статики - не нужно представлять экземпляр класса для использования данного члена; однако с абстрактным, каждый ожидает, что экземпляр будет иметь производный класс, который обеспечивает конкретную реализацию.

Я могу понять, почему вам нужна такая комбинация, но факт - единственный эффект, который будет отрицать использование использования 'this' или любых нестатических членов. То есть родительский класс будет определять ограничение в реализации производного класса, даже если нет никакого основного различия между вызовом абстрактного или "статического абстрактного" члена (так как для этого потребуется конкретный пример, чтобы выяснить, какую реализацию использовать)

Ответ 2

Вы не можете.

Место для этого - с атрибутами.

Например,

[Name("FooClass")]
class Foo
{
}

Ответ 3

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

Почему бы не просто классический способ?

abstract class AbstractBase
{
    protected string _Description = "I am boring abstract default value";
}

class Foo : AbstractBase {

     public Foo() {
       _Description = "I am foo!";
     }
}

Ответ 4

Если вы не против откладывать реализации, чтобы разумно реализовать свойство Description, вы можете просто сделать

public abstract string ClassDescription {get; } 
// ClassDescription is more intention-revealing than Description

И реализация классов будет делать что-то вроде этого:

static string classDescription="My Description for this class";
override string  ClassDescription { get { return classDescription; } }

Затем ваши классы должны следовать контракту о наличии описания, но вы оставляете его для них, чтобы сделать это разумно. Нет способа указать реализацию в объектно-ориентированном режиме (за исключением жестоких, хрупких хаков).

Однако, на мой взгляд, это описание представляет собой метаданные класса, поэтому я бы предпочел использовать механизм атрибутов, как описывали другие. Если вас особенно беспокоит многократное использование рефлексии, создайте объект, который отражает ваш атрибут, и сохраните словарь между типом и описанием. Это минимизирует отражение (кроме проверки времени выполнения, что не так уж плохо). Словарь может быть сохранен как член любого класса, который, как правило, нуждается в этой информации, или, если клиенты по всему домену требуют его, через одноэлементный или контекстный объект.

Ответ 5

Это не статично, если его нужно вызвать в экземпляре.

Если вы не вызываете его в экземпляре, тогда нет никакого полиморфизма в игре (то есть ChildA.Description полностью не связан с ChildB.Description в отношении языка).

Ответ 6

Вы можете сделать "абстрактный" базовый метод throw Exception, поэтому разработчик "предупреждается", если он пытается вызвать этот метод на дочернем классе без переопределения.

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