简体   繁体   中英

C# Return Type should this.getType()

I have a Function in C# and it have to return the type of the Class. Also in subclasses which extends the class.

Like:

public class A
{
    public typeof(this) Method()
    {
        //Code
    }
}
public class B : A {

    public override typeof(this) Method() {
        //Code
    }
}

So the Method in class A should have the return type A. And the Method in class B should have the return tpye B.

Is there a way to do it?

No, this isn't possible. What you're asking for is called a covariant return type, but C# doesn't support this. The closest you can get is either this:

public class A
{
    public virtual A Method()
    {
        //Code returning an A
    }
}

public class B : A 
{
    public override A Method() 
    {
        //Code returning a B
    }
}

Which is legal because every B is also an A , or you can use generics instead of inheritance:

public class Foo<T>
{
    public virtual T Method()
    {
        //Code
    }
}

And then you can have Foo<A> and Foo<B> -- however, Foo cannot depend on any specifics of T . You can combine this with inheritance, which will sort of achieve what you want:

public class A : Foo<A> 
{
    // And now A has a Method that returns A
}

public class B : Foo<B> 
{
    // And now B has a Method that returns B
}

But the problem with this approach is that you will have a hard time actually implementing Method in a meaningful way, because in Foo you cannot use anything specific to the type. To make this explicit, you could make Method abstract:

public abstract class Foo<T>
{
    public abstract T Method();
}

public class A : Foo<A> 
{
    public override A Method() 
    {
        // Code
    }
}

public class B : Foo<B> 
{
    public override B Method() 
    {
        // Code
    }
}

I'm having a hard time imagining a scenario where you can actually make use of this, but at least it meets the requirements.

Last but not least, you are not required to use inheritance -- does B really need to derive from A or could you inherit from some common base that does not use Method ?

Depending on what your method is trying to do, it might be possible to achieve what you want by using extension methods.

public class A { }

public class B : A { }

public static class AExtension {
    public static T Method<T>(this T target) where T: A {
        // do your thing here.

        return target; // or, return a new instance of type T.
    }
}

You can then call Method() and let C# infer the generic argument:

var a = new A();
a = a.Method(); // C# will infer T as A.

var b = new B();
b = b.Method(); // C# will infer T as B.

The downside to this approach is, of course, that you cannot access non-public members of your classes in Method() , unless you use reflection.

There is a way to do this, actually.

class A {
    public A Method () { ... return this; }
}

class B : A {
    new public B Method () => (B)base.Method();
    // or { base.Method(); return this; }
}

Make sure you only use this if you know that the base returns this .

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM