Добавление сеттера к виртуальному свойству в C # - PullRequest
9 голосов
/ 11 ноября 2010

У меня есть такая ситуация:

public abstract class BaseClass 
{
   public abstract string MyProp { get; }
}

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

public class Derived1 : BaseClass
{
    public override string MyProp { get { return "no backing store"; } }
}

Это отлично работает.Тем не менее, некоторые из производных классов требуют более традиционного резервного хранилища.Но, независимо от того, как я пишу это, как на автоматическом свойстве, или с явным резервным хранилищем, я получаю ошибку:

public class Derived2 : BaseClass
{
    public override string MyProp { get; private set;}
}

public class Derived3 : BaseClass
{
    private string myProp;
    public override string MyProp 
    { 
        get { return myProp;} 
        private set { myProp = value;}
    }
}

Derived2.MyProp.set ': невозможно переопределить, поскольку' BaseClass.MyProp 'не имеет переопределенного метода доступа set

Как мне заставить это работать ??

Ответы [ 4 ]

11 голосов
/ 11 ноября 2010

Лучшее, что вы можете сделать, это реализовать свойство как virtual вместо abstract. Создайте блоки get и set для каждого броска NotSupportedException в базовом классе и соответственно измените поведение в производных классах:

public virtual string MyProp {
    get {
        throw new NotSupportedException();
    }
    set {
        throw new NotSupportedException();
    }
}
3 голосов
/ 11 ноября 2010

В принципе, вы не можете.Добавляя сеттер, вы изменяете определение свойства, поэтому оно не «переопределяет» базовое свойство.Это так же, как если бы вы пытались переопределить метод и добавить к нему другой параметр - они будут рассматриваться как разные методы (перегружены).Поскольку свойства не могут быть перегружены, это не будет работать.

Вам просто нужно добавить другой метод для установки значения (возможно, с protected доступностью).

0 голосов
/ 22 июля 2013

Я бы предложил избегать виртуальных или абстрактных свойств.Вместо этого используйте не виртуальное свойство, которое связывает с защищенными виртуальными или абстрактными методами get / set.Это позволит производным классам переопределять методы, а также скрывать свойство с тем, у которого есть разные модификаторы доступа.Поскольку само базовое свойство будет не виртуальным, его никогда не придется переопределять, поэтому конфликт имен с новой версией не имеет значения.

0 голосов
/ 11 ноября 2010

Предложение Брэдли хорошо, но в случаях, когда только Сеттер должен быть виртуальным, я сделал одну вещь:

public class Root
{
    private string _MyProp;
    public string MyProp 
    {
        get { return _MyProp;}
        set { _MyProp = SetMyProp(value); }
    }
    protected virtual string SetMyProp(string suggestedValue)
    {
        return suggestedValue;
    }
}
public class Child
    : Root
{
    protected override string SetMyProp(string suggestedValue)
    {
        string oReturn = base.SetMyProp(suggestedValue);
        // Do some sort of cleanup here?
        return oReturn;
    }
}

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

...