Reputation: 5083
How I implement a generic method defined in a superclass in multiple subclasses? I need the correct subclass method to be decided by the type of the calling subclass instance:
var someClassObj = new SubClass();
var = someClassObj.BuildList(v1, v2);
public abstract class SomeBase
{
public List<T> BuildList<T>(int v1, int v2)
{
var results = new List<T>();
for (int i = v1; i < v2; i++)
{
results.Add(AddItem<T>());
}
return results;
}
protected abstract T AddItem<T>();
}
public class SubClass : SomeBase
{
protected override BusinessThing AddItem<T>()
{
var entity = new BusinessThing();
entity.Name1 = "1";
entity.Name2 = "2";
entity.Name3 = "3";
return entity;
}
}
public class BusinessThing
{
public string Name1 { get; set; }
public string Name2 { get; set; }
public string Name3 { get; set; }
}
The above does not build: Cannot change return type when overriding method 'T SomeBase.AddItem()'
Upvotes: 1
Views: 267
Reputation: 7773
If you don't want to have generic classes as Daniel suggests, you can also tell the compiler what T is using the where
clause to restrict the generic type:
public abstract class SomeBase
{
public List<T> BuildList<T>(int v1, int v2) where T: BusinessThing
{
var results = new List<T>();
for (int i = v1; i < v2; i++)
{
results.Add(AddItem<T>());
}
return results;
}
protected abstract T AddItem<T>() where T:BusinessThing;
}
public class SubClass : SomeBase
{
protected override T AddItem<T>()
{
var entity = new BusinessThing();
entity.Name1 = "1";
entity.Name2 = "2";
entity.Name3 = "3";
return (T)entity;
}
}
Then use it as follows:
var someClassObj = new SubClass();
var list = someClassObj.BuildList<BusinessThing>(5, 7);
This also allows you to use a derived ConcreteBusinessThing class which derives from BusinessThing which should also work using:
public class SubClass : SomeBase
{
protected override T AddItem<T>()
{
var entity = new ConcreteBusinessThing();
entity.Name1 = "1";
entity.Name2 = "2";
entity.Name3 = "3";
return (T)(object)entity; // ugly cast but is always ok
}
}
and calling it with:
var someClassObj = new SubClass();
var list = someClassObj.BuildList<ConcreteBusinessThing>(5, 7);
Upvotes: 1
Reputation: 174329
You would make your base class generic instead of its methods:
public abstract class SomeBase<T>
{
public List<T> BuildList(int v1, int v2)
{
var results = new List<T>();
for (int i = v1; i < v2; i++)
{
results.Add(AddItem());
}
return results;
}
protected abstract T AddItem();
}
public class SubClass : SomeBase<BusinessThing>
{
protected override BusinessThing AddItem()
{
var entity = new BusinessThing();
entity.Name1 = "1";
entity.Name2 = "2";
entity.Name3 = "3";
return entity;
}
}
Upvotes: 3