Исключение переполнения стека, выброшенное из переопределенного свойства из абстрактного базового класса - PullRequest
0 голосов
/ 24 августа 2009

У меня есть базовый класс со следующим (обрезанным для краткости) объявлением:

public abstract class MyBaseClass
{    
  public int RecordId { get; private set; }
  public string ObjectName { get; set; }
  public abstract string Status { get; set; }

  public GetMyObject(int id)
  {
     MyObject myObject = context.GetObjectById(id);
     this.RecordId = myObject.RecordId;
     this.ObjectName = myObject.ObjectName;
     this.Status = myObject.Status
  }
}

Который используется следующим классом:

public class MySpecificClass : MyBaseClass
{
   public override string Status
   {
      get
      {
         if(this.Status == "something")
           return "some status";
         else
           return "some other status";
      }
      set
      {
         this.Status = value;
      }
   }

   public GetMySpecificObject(int id) : base(id)
   {
   }
} 

Теперь, когда я связываю свой конкретный объект с моей моделью (моя реализация оказывается MVC), объект возвращается просто отлично, если я получаю доступ только к RecordID и ObjectName, но я получаю исключение переполнения стека, если методы доступа get или set в мой (переопределенный) статус попадет.

Я уже нашел похожий вопрос на SO ...

Почему набор свойств генерирует исключение StackOverflow?

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

Спасибо!

Ответы [ 3 ]

4 голосов
/ 24 августа 2009

Это «По замыслу».

В установщике состояния вы вызываете this.Status = value. Status - это виртуальное свойство, поэтому оно будет привязано прямо к установщику MySpecificClass.Status.

Если вы хотите получить доступ к базовому свойству, используйте base. вместо

base.Status = value;
1 голос
/ 24 августа 2009

Объявление абстрактного свойства в базовом классе просто гласит: «производные классы ДОЛЖНЫ реализовывать свойство с именем Status с использованием методов получения и установки». В вашем производном классе вызов this.Status внутри получателя недопустим (вызывает переполнение стека).

Чтобы исправить это, используйте свойство с вспомогательным полем в производном классе:

public abstract class MyBaseClass
{
    public abstract string Status { get; set; }
}


public class MySpecificClass : MyBaseClass
{
   private string _status;
   public override string Status
   {
       get
       {
          if(this._status == "something")
            return "some status";
          else
            return "some other status";
       }
       set
       {
           _status = value;
       }
   }

}
0 голосов
/ 24 августа 2009

Установщик в MySpecificClass не должен быть проблемой, но определитель определенно - внутренне, вызов экземпляра Status MySpecificClass будет делать вызов самому себе, чтобы увидеть, какое возвращаемое значение будет делать вызов самому себе чтобы увидеть ... хорошо. Вы поняли идею.

Я бы использовал защищенную переменную класса, а не авто-свойство.

public abstract class MyBaseClass
{
    protected string _status;
    public virtual string Status
    {
        get { return _status; }
        set { _status = value; } 
    }
}

public class MySpecificClass : MyBaseClass
{
    public override string Status
    {
        get
        {
            if(_status == "something")
                return "some status";
            else
                return "some other status";
        }
        set
        {
            _status = value;
        }
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...