Какое исключение бросить, когда установщик свойства не разрешен? - PullRequest
18 голосов
/ 21 сентября 2011

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

public virtual string Name { get; set; }

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

public override string Name
{
    get { return "Fixed Name"; }
}

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

Поэтому я подумал, что сделаю что-то вроде:

public override string Name
{
    get { return "Fixed Name"; }
    set { throw new Exception(); } //which exception type?
}

два (связанные вопросы):

  1. Есть ли лучший шаблон для меня?
  2. Если я должен использовать вышеуказанный шаблон, какое исключение использовать?

Редактировать : Некоторые причины, по которым одно исключение будет предпочтительнее другого, были бы хорошими.Мой коллега и я имели один и тот же аргумент между NotSupported и InvalidOperation.

Ответы [ 5 ]

24 голосов
/ 21 сентября 2011

Бросок NotSupportedException исключение. Цитата по ссылке:

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

Мое мнение таково, что InvalidOperationException не является правильным вариантом. Цитата из MSDN:

Исключение, которое выдается, когда вызов метода недопустим для текущее состояние объекта.

Нет ничего о текущем состоянии в вашей ситуации. Дело в том, что классовый контракт не поддерживает операцию.

8 голосов
/ 21 сентября 2011

Это нарушает принцип подстановки Лискова, и поэтому это плохая идея.

4 голосов
/ 21 сентября 2011

Если вы можете попытаться переместить установщик в конструктор базового класса и сделать его закрытым.Или, как Джон предложил создать абстрактный базовый класс / интерфейс с геттерами, которые поддерживаются во всех реализациях.

Это позволило бы избежать всей ситуации с исключением исключения.

1 голос
/ 22 июля 2013

Если базовый класс на самом деле позволяет устанавливать имя (в отличие от предоставления абстрактного установщика, который не гарантированно работает), производные классы также должны это делать.Если вам нужна иерархия, которая включает в себя некоторые классы, в которых имя может быть установлено, а некоторые - там, где это невозможно, оба вида классов должны наследоваться от абстрактного ReadableXX класса с не виртуальным свойством чтения-записи Name, которое связывает в абстракциюGetName и SetName методы.Он также должен предоставлять некоторые средства указания, будет ли поддерживаться SetName (например, метод CanSetName).Вариант класса, доступный только для чтения, может определять «новое» свойство Name только для чтения, которое будет связываться с GetName и иметь SetName override throw NotSupportedException.Если в спецификации для класса сказано, что SetName будет работать только в том случае, если CanSetName вернет true, то SetName выдает исключение в классах, где CanSetName возвращает false, не нарушит принцип подстановки Лискова.

0 голосов
/ 21 сентября 2011

Здесь я бы пошел за NotImplementedException .

...