从抽象基类的重写属性抛出的堆栈溢出异常

时间:2009-08-24 18:51:40

标签: c# properties override abstract

我有一个基类,其中包含以下内容(为简洁而修剪)声明:

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上找到了类似的问题......

Why does Property Set throw StackOverflow exception?

...但是通过自动属性实现,我的代码看起来是正确的,而不是创建一个无限循环(但似乎确实如此)。关于如何正确覆盖该属性的任何想法?

谢谢!

3 个答案:

答案 0 :(得分:4)

这是“按设计”。

在状态设置器中,您调用此状态.Status = value。 Status是一个虚拟属性,因此它将绑定回MySpecificClass.Status的setter。

如果要访问基本属性,请使用base。代替

base.Status = value;

答案 1 :(得分:1)

基类中的抽象属性声明只是声明:“派生类必须实现一个名为Status的属性,带有getter和setter”。在派生类中,在getter中调用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;
       }
   }

}

答案 2 :(得分:0)

MySpecificClass中的setter应该不是问题,但getter肯定是 - 在内部,对MySpecificClass的Status实例的调用将调用自己来查看返回哪个值将调用自身看...好吧。你明白了。

我使用受保护的类变量而不是自动属性。

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;
        }
    }
}