I have the following code which has a Base
class containing an abstract template method, which in the derived classes is overridden using concrete types.
class MyObj
{
private string name;
public string Name { get; set; }
};
class MyObj2
{
private string value
public string Value { get; set; }
}
abstract class Base
{
public abstract string toString<T>(T t);
public void doSomething<T>(T t)
{
string myValue = toString<T)(t);
...
}
};
class MyClass : Base
{
public override string toString<MyObj>(MyObj o)
{
return o.Name;
}
}
class MyClass2 : Base
{
public override string toString<MyObj2>(MyObj2 o)
{
return o.Value;
}
}
But the compiler doesn't like the implementations of toString()
in MyClass
or MyClass2
, giving an error message along the lines of:
'MyObj' does not contain a definition for 'Name' and no extension method 'MyObj' accepting a first argument of type 'MyObj' could be found (are you missing a using directive or an assembly reference?)
You appear to be trying to provide an implementation for one specific type argument. You can't do that, and it doesn't make sense - it's not clear what would happen if the caller passed in a different type argument, e.g.
Base b = new MyClass2();
b.doSomething<int>(10);
(At the moment, your MyObj
and MyObj2
in the methods are being treated as type parameters rather than as the types themselves, which is why the compiler doesn't know anything about your Name
or Value
properties.)
It sounds like really it should be the class which is generic:
abstract class Base<T>
{
public abstract string ToString(T t);
public void DoSomething(T t)
{
string myValue = ToString(t);
...
}
}
class MyClass : Base<MyObj>
{
public override string ToString(MyObj o)
{
return o.Name;
}
}
class MyClass2 : Base<MyObj2>
{
public override string ToString(MyObj2 o)
{
return o.Value;
}
}
At this point, the previously-problematic code wouldn't work, because you'd to use Base<MyObj2>
as the variable type instead of just Base
, and you could only pass a MyObj
to DoSomething
.
(You might also want to consider making the ToString
method protected instead of public. That's more common for the template method pattern, although certainly not required.)
See more on this question at Stackoverflow