Частичное переопределение виртуального автоматического свойства в дочернем классе

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

Следующий код действителен и компилируется:

public class Parent
{
    public virtual object TestProperty { get; set; }
}

public class Child : Parent
{
    private string _testValue = "Hello World!";

    public override object TestProperty
    {
        get { return _testValue; }
    }
}

public class Consumer
{
    Parent p = new Child();

    public Consumer(){ p.TestProperty = 3; }
}

У меня вопрос:

Почему C # позволяет мне частично переопределять свойство TestProperty auto в дочернем элементе, когда это ведет к частично непредсказуемому поведению? Есть ли практическое применение?

Мне разрешено устанавливать значение TestProperty с помощью родительского установщика (я проверил генерируемый IL, и установщик все еще устанавливает объект поддержки в родительском классе), даже если значение недоступно для публики.


person Justin Niessner    schedule 07.10.2010    source источник
comment
Я уверен, что есть много таких странных вещей, которые будут компилироваться и работать, но не имеют практического применения и могут иметь неприятные побочные эффекты. Молотки строят дома или разбивают пальцы, в зависимости от того, как вы их используете :)   -  person Dave Swersky    schedule 07.10.2010
comment
@ Дэйв - Совершенно верно. Я просто хочу удостовериться, что в этом случае удары молотком по большим пальцам не служат какой-то цели, которую я просто не вижу.   -  person Justin Niessner    schedule 07.10.2010


Ответы (2)


Такое поведение согласуется с неавтоматически реализуемыми свойствами в C #. Всегда можно было переопределить только метод get или set для виртуального свойства. Следовательно, невозможность использования автоматически реализуемого свойства создаст ненужную несогласованность.

Например, следующее является законным

class A
{
    public virtual int P1
    {
        get { return 42; }
        set { }
    }
}

class B : A
{
    public override int P1
    {
        get { return 18; }
    }
}
person JaredPar    schedule 07.10.2010
comment
Справедливо. Таким образом, вопрос не ограничивается автоматическими свойствами. Все еще немного нечетко в практическом применении. Если я объявляю все свое свойство как единое целое, и эта единица состоит из операций получения и установки ... зачем мне переопределять одно и оставлять другое с потенциально запутанным поведением? - person Justin Niessner; 07.10.2010
comment
@Justin, части свойства get и set - это принципиально разные методы, поэтому имеет смысл переопределить их независимо. С точки зрения того, почему вы хотели бы, возможно, я хочу добавить дополнительную проверку в сеттер или поведение кеширования в получателе, но сохранить поведение по умолчанию для другого. Я уверен, что есть несколько допустимых вариантов использования для этого. - person JaredPar; 07.10.2010
comment
@JaredPar - я понимаю, что это принципиально разные методы, но логически они связаны в моем сознании. Однако с точки зрения языкового дизайна, почему бы не потребовать переопределения обоих, а затем, если вы хотите сохранить существующую функциональность, вы просто вызываете return base.TestProperty () ;? (может быть, поэтому я не создан для разработки языков) - person Justin Niessner; 07.10.2010
comment
@Justin Я думаю, где вы спотыкаетесь, это предполагает, что они логически связаны. На самом деле это так в подавляющем большинстве случаев. Но они не должны быть, и даже в том случае, если исходные 2 возможны, можно правильно переопределить одно, но не другое (подумайте, что кеширование в производном типе переопределяется). Заставлять пользователя переопределять и то, и другое, когда никто на самом деле не переопределяет, ... ну неправильно :) - person JaredPar; 07.10.2010
comment
@JaredPar - И вот оно. Вы когда-нибудь задавали вопрос, а затем понимали, что после того, как кто-то даст вам ответ, вы знали это все время, но блокировали его, потому что вы застряли на Wha !? часть? Спасибо! - person Justin Niessner; 07.10.2010
comment
@ Джастин, такое случалось много раз;) - person JaredPar; 07.10.2010

Но разве это не имеет смысла для сеттера? Если вы частично переопределите только установщик, это может быть полезно, чтобы вы могли ответить на это событие в дополнение к вызову base.TestProperty = value, не беспокоясь также о стандартном переопределении получателя.

person Kirk Woll    schedule 07.10.2010