I have an abstract immutable base class that defines enforces child classes to be initialized, hence the abstract calls instead of an interface:
public abstract BaseLookup<TPoint, TItem>
{
protected IEnumerable<TItem> items = null;
protected BaseLookup(IEnumerable<TItem> items)
{
this.items = items;
this.Initialize();
}
public abstract void Initialize();
// problem deciding which one
// either implementing a method...
public abstract TItem GetItem(TPoint point);
// ...or assigning a method
public Func<TPoint, TItem> GetItem { get; protected set; }
}
GetItem
execution has to be as fast as possible. During initialization stage I have to check initial items and decide what GetItem
method should do. It can be one of many implementations based on this set of items.
Since GetItem
method has to be as fast as possible it seems much better to have it defined as a property and assign it a straight forward branch-less lambda expression. But using above definition child classes are not forced to set any values to it so implementers may create an invalid child class. Defining an abstract
accessor on the property would force them to implement the property which is semantically the same as implementing a method. This doesn't enforce property assignment.
But if I implement it as an overridden abstract method that particular method will need to include all those branches that branch based on items. This means that these branches would get evaluated every time I'd call the method hence making it slow(er).
What I'm actually looking for is a way to force child class implementers to set GetItem
property.
How am I supposed to do that?
Also take into consideration that this class will get initialized once and then be used many many times. Used as in calling the GetItem
method.
public class IteratorLookup<TPoint, TItem> : BaseLookup<TPoint, TItem>
{
private TItem single = null;
public IteratorLookup(IEnumerable<TItem> items) : base(items);
public override void Initialize()
{
if (this.items != null && this.items.Count > 0)
{
if (this.items.Count > 1)
{
this.GetItem = point => this.items[this.GetIndex(point)];
}
else
{
this.GetItem = irrelevant => this.single;
}
}
else
{
this.GetItem = irrelevant => null;
}
}
private int GetIndex(TPoint point) { ... }
}
public class IteratorLookup<TPoint, TItem> : BaseLookup<TPoint, TItem>
{
private TItem single = null;
public IteratorLookup(IEnumerable<TItem> items) : base(items);
public override void Initialize()
{
// implementing minor speed up
if (this.items != null && this.items.Count == 1)
{
this.single = items[0];
}
}
public override TItem GetItem(TPoint point)
{
if (this.items != null && this.items.Count > 0)
{
if (this.items.Count > 1)
{
return this.items[this.GetIndex(point)];
}
return this.single;
}
return null;
}
private int GetIndex(TPoint point) { ... }
}
Since GetItem method has to be as fast as possible it seems much better to have it defined as a property and assign it a straight forward branch-less lambda expression
What makes you think it will be faster than a method? The abstract method is the way to go here. It's a more natural approach, and it doesn't have the issue that the property might not be initialized.
But if I implement it as an overridden abstract method that particular method will need to include all those branches that branch based on items. This means that these branches would get evaluated every time I'd call the method hence making it slow(er).
Not sure what you mean by that... what prevents you from putting in the GetItem
method the same code you would have put in a Func<TPoint, TItem>
in the GetItem
property?
As a side note, you should probably think twice about calling a virtual method ( Initialize
) in the constructor, it can lead to unexpected issues: the base constructor is executed before the derived constructor, but it's always the most derived implementation of Initialize
that will be called; so if the derived implementation of Initialize
relies on things that are initialized in the derived class constructor, it will fail because they won't be initialized yet.
You need to inject somewhat an aspect to your issue. Properties are quite straight forward where you cannot ensure that subclasses has invoked it or not.
You make take advantage of GetItem
method making it from abstract
to virtual
and your base class's implementation will be throwing an exception
.
public virtual TItem GetItem(TPoint point)
{
throw new Exception("Please implement GetItem method");
}
Now, any of the subclasses not overriding this method will fall into exception and ensure subclasses to implement GetItem
method.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.