views:

343

answers:

4

Hi all,

I have a base class with the following (trimmed for brevity) declaration:

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

Which is used by the following class:

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)
   {
   }
}

Now when I bind my specific object to my model (my implementation happens to be MVC) the object is returned just fine if I only access the RecordID and the ObjectName, but I get a stackoverflow exception if the get or set accessors to my (overridden) Status is hit.

I found a similiar question on SO already...

http://stackoverflow.com/questions/367192/new-to-c-why-does-property-set-throw-stackoverflow-exception

... but going by the auto-property implementation, my code looks like it would be correct and not create an infinate loop (but this does appear to be the case). Any ideas on how I would correctly override that property?

Thanks!

+4  A: 

This is "By Design".

In the setter of Status you are calling this.Status = value. Status is a virtual property and hence it will bind right back to the setter of MySpecificClass.Status.

If you want to access the base property use base. instead

base.Status = value;
JaredPar
@JaredPar: can base.Status be used, when it is abstract?
shahkalpesh
@shahkalpesh: abstract just means that you can't create the base class itself. However, all derived classes still "contains" the abstract base class, so all its members are there.
Brian Rasmussen
@Brian: Please help me understand, how can base.Status be used when it is declared abstract. I think, either I am missing something or I need to learn c# fundamentals.
shahkalpesh
In my getter if I change this.Status to base.Status I get the following complile time error "Cannot call an abstract base member".From the setter I cannot access base.Status (intelli-crack doesnt like it).
Justin
@shahkalpesh, I believe you are correct. But I appreciate your effort Brian :)
Justin
This answer is not correct. base.Status is declared abstract, so it can't be called.
jeroenh
@jeroenh, I was indicating shahkalpesh was correct, not the answer, sorry for the confusion. I marked a (probably not the only) correct answer below.
Justin
A: 

Where is the backing variable for Status property?

shahkalpesh
The backing variable isn't declared since I was using C# 3.0's auto property feature.
Justin
@Justin: Yes but it will be required, if you are basing your decision off it. Either there should be a base class property (non-abstract) OR there should be a backing variable, AFAIK.
shahkalpesh
A: 

The setter in MySpecificClass shouldn't be a problem, but the getter definitely is - internally, a call to an instance of MySpecificClass's Status will be making a call to itself to see which value to return which will make a call to itself to see... well. You get the idea.

I'd use a protected class variable rather than an auto-property.

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;
        }
    }
}
48klocs
Attempting to make the change to a protected class variable throws the following compile time error on the get and set lines:"Cannot declare a body because it is marked abstract"
Justin
I should have declared the base property as a virtual instead of an abstract.
48klocs
That got it, thanks klocks!
Justin
+1  A: 

The abstract property declaration in the base class just states: "derived classes MUST implement a property called Status, with a getter and setter". In your derived class, calling this.Status inside your getter is illegal (causes the stack overflow).

To fix this, use a property with a backing field in your derived class:

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

}
jeroenh