What is the best way to implement a Must Set Property for a Base class?
I have a simple basic question about C# and inheritance.
In the below example, I'm showing 2 ways of setting a must set properties (CaptionDisplayText and Firstname):
public abstract class BaseClass
{
private string _firstName;
protected BaseClass(string captionDisplayText)
{
this.CaptionDisplayText = captionDisplayText;
this._fir开发者_JS百科stName = this.GetFirstName();
}
protected string CaptionDisplayText { get; private set; }
protected abstract string GetFirstName();
}
public class DerivedClass : BaseClass
{
protected DerivedClass():base(String.Empty)
{
}
protected override string GetFirstName()
{
return String.Empty;
}
}
Approach 1, CaptionDisplayText, introduces a property and sets it in the constructor whereas approach 2 introduces an abstract method which is overridden in the Derived class.
I know Approach2 is bad if the method was virtual rather than abstract but here it's abstract which means it is executed before the constructor of the base class and that will be fine.
I'm having 10-15 properties/fields which have to be set by my derived classes so I'm thinking which approach would be more maintainable, readable and testable.
I think approach 1 is more testable whereas approach 2 is much more readable. Approach 2 would also be testable as the mock object will have to implement the abstract members anyway.
Which way is best in your view and is there a third way?
Many thanks,
Doing logic in the constructor is not the way to go if you do want to make the class testable. So by doing this._firstName = this.GetFirstName(); will introduce extra test effort, the code is called even if you do not want to do anything with the first name. In the first approach you could have filled it with a null, which indicates it is not important for your test.
Have you thought of using CodeContracts and a ClassInvariant?
By me, the best is 1st one, cause it esplicitly sets the data and provide the information to caller what have to be set mandatory just during the construction of the object.
The only "problem" you can meet here is a quantity of properties, at this point like a parameters in ctor, which weird enough to see 15 parameters in one method. But may be this can be "avoided" (difficult to know for me without knowing your app) by ctor overloading, if you from some property values set can deduct other properties "default" value.
There is obviuolsy a Dictionary/HashSet or whatever solution too, but to me, that solution is wierd too.
Hope this helps.
Regards.
To me, this looks confusing. Why are you using a GetFirstName to set the first name. Isn't it better to do this as an abstract SetFirstName method and do the logic in there instead of hiding it in the constructor? I agree it is a tricky/nice way of doing it but might be confusing to some people. In the derived class when you implement the GetFirstName method, it is not intuitive that you are going to set this in the base class.
something like protected abstract string SetFirstName(); This way the derived classes always have to override this method and you set the first name in it. Of course you have to make the firstname property protected.
It is not a "must set" approach. But at least gives you a hint. Or Perhaps, just change the GetFirstName to SetFirstName ;)
精彩评论