开发者

Creating an object of the type a static method is called on in an inheritance chain in C#

I am trying to do something like this in C#

public class ParentClass {
  public static ParentClass GetSomething()
  {
    var thing = new // ?????
    return thing;
  }
}

public class ChildClass : ParentClass {
}

And then I want to be able to call the static method on the child class like so:

ChildClass bla开发者_如何学Goh = ChildClass.GetSomething();

e.g. When calling the static method on the child class I want to instantiate an instance of the child class. But I just want the static method defined on the parent. Is this at all possible? I'd be happy even with:

ChildClass blah = (ChildClass) ChildClass.GetSomething();

Thanks!


This smells awful, but you could do this:

public class ParentClass {
    public static T GetSomething<T>() where T : ParentClass, new() {
        return new T();
    }
}

Usage:

ParentClass parent = ParentClass.GetSomething<ParentClass>();
ChildClass child = ChildClass.GetSomething<ChildClass>();

This is legit too:

ParentClass parent = ChildClass.GetSomething<ParentClass>();

which contributes to the smelliness of this (yes it just compiles to ParentClass parent = ParentClass.GetSomething<ParentClass>() but it still smells).


You cannot 'override' static methods. But you can use generics to tell the ParentClass which derived class you actually means. It's somewhat ugly but it works:

class ParentClass<T> where T : ParentClass<T>, new()
{
    public static T GetSomething()
    {
        T thing = new T();
        return thing;
    }
}

class ChildClass : ParentClass<ChildClass>
{
}

Test:

ChildClass x = ChildClass.GetSomething(); // works


This line:

ChildClass blah = ChildClass.GetSomething();

is compiled to exactly the same IL as this line:

ChildClass blah = ParentClass.GetSomething();

(when ChildClass doesn't declare its own GetSomething method).

I would prefer:

ChildClass blah = ParentClass.GetSomething<ChildClass>();

It's like your casting version, but with angle brackets and the type name coming after instead of before the method name :) (Basically Jason's suggestion, now I've seen it!)

However, this is now somewhat independent of ParentClass - you can define it anywhere that's useful:

public static class FactoryUtil
{
    public static T CreateInstance<T>() where T : ParentClass
    {
        ...
    }
}

... or you could provide a factory as a dependency where you need it, making things more testable, potentially...


C# doesn't let you override static methods.

There's nothing stopping you, though, from redefining a new static method on ChildClass that hides the ParentClass method. Would doing that help?

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜