可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
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 stack overflow exception if the get or set accessors to my (overridden) Status is hit.
I found a similar question on SO already...
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 infinite loop (but this does appear to be the case). Any ideas on how I would correctly override that property?
Thanks!
回答1:
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; } } }
回答2:
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;
回答3:
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; } } }