Andrey Khataev
Andrey Khataev

Reputation: 1343

Generic method declaration

I have hierarchy of classes:

class A{}
class B: A {}
class C:B {}

is it possible to implement method in class A and it would be inherited by derived classes B and C and so on and that method should return value of class type?

A val = A.method(); (val is A)
B val = B.method(); (val is B)
C val = C.method(); (val is C)

And I don't want use of generics in call of this method, ie:

C val = C.method<C>();

Guys, excuse me, one elaboration, this method should be static.

I don't want to use generic in method istelf, because it forces to point type that method should return, whereas method should return type of its class.

class A
    {
      Method<T>()
      {
         T result;
         return result;
      }
    }

If I have such method I can change return type:

D result = A.Method<D>();

but I wanted it to return value of type A;

Upvotes: 1

Views: 294

Answers (3)

Guffa
Guffa

Reputation: 700152

No, that is not possible.

To call the method like that it would have to be static, and static methods are not inherited.

Using B.method() to call a static method in A is the same as using A.method(). The compiler just uses the type to determine where the method is, but it's impossible for the method to know if it was called using the A or B type.

Upvotes: 3

Ben Voigt
Ben Voigt

Reputation: 283614

Using some design patterns from C++ makes this easier:

class A
{
    protected virtual A method_impl() { return new A(); }
    public A method() { return method_impl(); }
}

class B : A
{
    protected override A method_impl() { return new B(); }
    public new B method() { return (B)method_impl(); }
}

class C : B
{
    protected override A method_impl() { return new C(); }
    public new C method() { return (C)method_impl(); }
}

Of course, this exact problem never arises in C++, which allows covariant return types for overrides.


Another way, using IoC pattern:

class A
{
    protected virtual void method_impl(A a) { a.initialize(); }
    public A method() { A result = new A(); method_impl(result); return result; }
}

class B : A
{
    public new B method() { B result = new B(); method_impl(result); return result; }
}

class C : B
{
    public new C method() { C result = new C(); method_impl(result); return result; }
}

Upvotes: 2

GregRos
GregRos

Reputation: 9103

Use an extension method:

class Program
    {
        static void Main(string[] args)
        {
            B x = new B();
            x.Method();
        }
    }

    public static class Ext
    {
        public static T Method<T>(this T obj)
            where T : A,new()
        {
            return new T();
        }
    }

    public class A
    {

    }

    public class B : A
    {

    }

Or a variation thereof. Note that you must have some public member capable of creating an instance of the specified type. To expound, the compiler 'guesses' the value of the type parameter. The method is still generic, but generic syntax is nowhere to be seen when the method is called (usually).

Upvotes: 2

Related Questions