Given the following classes:
ClassA
{
public ClassA DoSomethingAndReturnNewObject()
{}
}
ClassB : ClassA
{}
ClassC : ClassA
{}
Well, the correct answer is no and, generally, this is a bad idea. If you are returning something completely different, find another way.
However, if you aren't returning something completely different, an interface can solve your issue. Instead of returning a class, return an interface and have classes A, B, and C return objects that implement that interface in the way they see fit.
I finally devised the following solution. For my case it's useful enough, but it assumes that ClassA knows about it's derivatives and is limited to those two options. Not really high-level thinking, but it works. :)
ClassA
{
public ClassA DoSomethingAndReturnNewObject()
{
if (this.GetType() == typeOf(ClassB))
{
return new ClassB(values);
}
else
{
return new ClassC(values):
}
}
}
ClassB : ClassA
{}
ClassC : ClassA
{}
What you're describing is a covariant return type and is not supported in C#.
However, you could create ClassA as an open generic and have the closed generic inheritors return their own type.
Example:
public abstract class ClassA<T> where T: ClassA<T>, new()
{
public abstract T DoSomethingAndReturnNewObject();
}
public class ClassB: ClassA<ClassB>
{
public override ClassB DoSomethingAndReturnNewObject()
{
//do whatever
}
}
You need to create a protected virtual method for the DoSomethingAndReturnNewObject
to use:
class ClassA
{
protected virtual ClassA Create()
{
return new ClassA()
}
public ClassA DoSomethingAndReturnNewObject()
{
ClassA result = Create();
// Do stuff to result
return result;
}
}
class ClassB : ClassA
{
protected override ClassA Create() { return new ClassB(); }
}
class ClassC : ClassA
{
protected override ClassA Create() { return new ClassC(); }
}
Note the return type remains ClassA but the object instance type will be the specific class.
Maybe generics will be your saviour. Take a look at this link: C# Generics Part 3/4: Casting, Inheritance, and Generic Methods
bstract class B<T> {
public abstract T Fct(T t);
}
class D1 : B<string>{
public override string Fct( string t ) { return "hello"; }
}
class D2<T> : B<T>{
public override T Fct(T t) { return default (T); }
}
class ClassA<T> where T : ClassA<T>, new()
{
public T DoSomethingAndReturnNewObject()
{
return new T();
}
}
class ClassB : ClassA<ClassB> { }
class ClassC : ClassA<ClassC> { }
Test:
ClassB b1 = new ClassB();
ClassB b2 = b1.DoSomethingAndReturnNewObject(); // returns instance of ClassB