По определению private
члены не могут быть переопределены.Если вы хотите, чтобы сеттер был перезаписываемым, вы можете пометить его protected
вместо private
.
private abstract class InheritanceTest
{
public virtual object Property
{
get { return null; }
protected set { }
}
public class Child : InheritanceTest
{
public override object Property
{
get { return null; }
protected set { base.Property = null; }
}
}
}
Чтобы более конкретно ответить на ваш вопрос относительно почему :
Поймите, что когда ваш код C # скомпилирован в код IL, на самом деле в конечном итоге получается 3 вещи для 1 свойства.
- Само свойство
Property
. - Метод с именем
get_Property()
, который является получателем. - Метод именует
set_Property()
, который является установщиком.
В своем коде вы сказали .NET, что "Iхочу свойство virtual
. Затем он каскадно обращается к этому уровню доступа к методам получения и установки. На самом деле, в коде IL свойства вообще не задают virtual
.
Для кода C #:
public virtual object Property { get; set; }
Сгенерированный код IL:
.property instance object Property() { ... }
.method public hidebysig newslot specialname virtual
instance object get_Property() cil managed
{ ... }
.method public hidebysig newslot specialname virtual
instance object set_Property() cil managed
{ ... }
Обратите внимание, что ключевые слова public
и virtual
применяются как к методам получения, так и к методам установки, но не к самому свойству.
Теперь, изменив код C # на:
public virtual object Property { get; private set; }
Вы сказали .NET, что хотите, чтобы ваш получатель получилnd методы установки должны быть виртуальными ... однако , затем он переходит в private set
, и этот уровень доступа переопределяет уровень доступа public
и virtual
для установщикаметод.Таким образом, сгенерированный код IL становится:
.property instance object Property() { ... }
.method public hidebysig newslot specialname virtual
instance object get_Property() cil managed
{ ... }
.method private hidebysig newslot specialname
instance object set_Property() cil managed
{ ... }
Обратите внимание, что теперь set_Property()
равно private
и больше не virtual
.На самом деле невозможно иметь private virtual
в .NET, потому что это не имеет смысла ... это все равно, что пытаться сказать: «Никакой другой класс не может увидеть это ... но производные классы могут переопределить эту вещь, которую онине может видеть или получить доступ ", который не имеет смысла.Производные классы не могут переопределить то, что они даже не видят.
Ключевое слово protected
в данном случае является правильной заменой, поскольку оно говорит .NET: «Только я и производные классы могут видеть или получать к нему доступ,и производные классы могут переопределять это свойство. "
Так что я думаю, что" короткий "ответ был бы просто", потому что в .NET вещи не могут быть private
и virtual
, поэтому компилятор принимаетболее ограниченный уровень доступа, который вы ему дали.
Кроме того, IMO сообщение об ошибке довольно корректно.
'Program.InheritanceTest.Child.Property.set': невозможно переопределить унаследованный член'Program.InheritanceTest.Property.set', поскольку он не помечен как виртуальный, абстрактный или переопределенный
Обратите внимание, что он говорит 'Program.InheritanceTest.Property.set'
, поэтому ".set" в конце ссылается навозможный метод set_Property()
, а не свойство Property
. И метод set_Property()
помечен только private
, потому что компилятор .NET увидел это и удалил virtual
из этого метода по причине, упомянутой выше.предположим, яБыло бы разумно иметь предупреждение компилятора или что-то, говорящее, что "virtual будет проигнорировано для" set ".
Надеюсь, это имеет больше смысла ...