Base class with virtual method and only implementing a guard clause
If you have a base class defined as follows:
public abstract class BaseMessageObject<T> where T : Entity
{
public string Message { get; set; }
public abstract BaseMessageObject<T> BuildMessage(T entity);
}
and you have a base class for HTMLObjectMessages defined as follows:
public abstract class HtmlMessageObject<T> : BaseMessageObject<T>
where T : Entity
{
public override abstract BaseMessageObject&l开发者_运维知识库t;T> BuildMessage(T entity);
}
and you have a concrete implementation of the HtmlMessage as follows:
public class SocialSecurityVerificationHtmlMessageObject<T>:HtmlMessageObject<T>
where T : SomeConcreteEntity
{
public override BaseMessageObject<T> BuildMessage(T entity)
{
SocialSecurityVerificationHtmlMessageObject<T> message =
new SocialSecurityVerificationHtmlMessageObject<T>();
//do some stuff to build the message
}
}
Is there any harm in placing guard clauses in the base MessageObject as follows:
public abstract class BaseMessageObject<T> where T : Entity
{
public string Message { get; set; }
public virtual BaseMessageObject<T> BuildMessage(T entity)
{
if (null == entity)
throw new ArgumentNullException(entity)
throw new NotImplemenetedException("");
}
}
Something about this feels wrong. Should this be refactored?
I would do it like this:
public abstract class BaseMessageObject<T> where T : Entity
{
public string Message { get; set; }
public BaseMessageObject<T> BuildMessage(T entity)
{
if (null == entity)
throw new ArgumentNullException(entity)
BuildMessageCore (entity);
}
protected abstract BaseMessageObject<T> BuildMessageCore(T entity);
}
public class SocialSecurityVerificationHtmlMessageObject<T> : HtmlMessageObject<T>
where T : SomeConcreteEntity
is conflict with base which is
public abstract class BaseMessageObject<T>
where T : Entity
different where T . u can't declare 2 different type parameter inherited line
u can do this
public class SocialSecurityVerificationHtmlMessageObject<T> : HtmlMessageObject<SomeConcreteEntity>
where T : SomeConcreteEntity
but the problem is your base class will never know what T really is.
You can use a code contract:
[ContractClass(typeof(BaseMessageObjectContract<>))]
public abstract class BaseMessageObject<T> where T : Entity {
public string Message { get; set; }
public abstract BaseMessageObject<T> BuildMessage(T entity);
}
[ContractClassFor(typeof(BaseMessageObject<>))]
abstract class BaseMessageObjectContract<T> : BaseMessageObject<T>
where T : Entity {
public override BaseMessageObject<T> BuildMessage(T entity) {
Contract.Requires<ArgumentNullException>(entity != null);
return null;
}
}
You should also enable runtime checking of your preconditions.
精彩评论