繁体   English   中英

从静态方法获取派生类型

[英]Get derived type from static method

我想从静态方法中获取派生类型。

我想做这样的事情

void foo()
{
  this.getType();
}

但在静态方法中

我知道

MethodBase.GetCurrentMethod().DeclaringType

返回基本类型,但我需要派生。

假设你的意思是你有这样的事情

class MyBaseClass
{
    public static void DoSomething()
    {
        Console.WriteLine(/* current class name */);
    }
}

class MyDerivedClass : MyBaseClass
{
}

并想要MyDerivedClass.DoSomething(); 打印"MyDerivedClass" ,那么答案是:

您的问题没有解决方案。 静态方法不像实例方法那样被继承。 您可以使用MyBaseClass.DoSomethingMyDerivedClass.DoSomething来引用DoSomething ,但两者都被编译为对MyBaseClass.DoSomething调用。 无法找出源代码中使用哪个进行调用。

我想你需要这样的场景:

void Main()
{
  Base.StaticMethod(); // should return "Base"
  Derived.StaticMethod();  // should return "Derived"
}


class Base
{
  public static void StaticMethod()
  {
    Console.WriteLine(MethodBase.GetCurrentMethod().DeclaringType.Name);
  }
}

class Derived: Base 
{
}

但是,此代码将返回

Base       
Base

这是因为静态方法调用在编译时被解析为对基类的调用,基类实际上定义了它,即使它是从派生类调用的。 线条

Base.StaticMethod();
Derived.StaticMethod();

生成以下 IL:

IL_0001:  call        Base.StaticMethod
IL_0006:  nop         
IL_0007:  call        Base.StaticMethod

一句话,做不到。

7 1/2 年后...

我想做同样的事情,这就是我发现这个问题的方式。 有一个解决方案接近所要求的内容,并且可能对搜索此问题的其他人有用。

我想要一个静态方法,它会返回一个类的实例,其中包含为我设置的所有基本设置。 以下工作:

void Main()
{
    ChildClassA cA = ChildClassA.SetFoo();
}

public abstract class BaseClass
{
    public bool Foo {get; set;}
}

public class ChildClassA : BaseClass
{
    public static ChildClassA SetFoo() => new ChildClassA{Foo = false};
}

public class ChildClassB : BaseClass
{
    public static ChildClassB SetFoo() => new ChildClassB { Foo = false };
}

这一切都很好,但我想把SetFoo函数放在基类中,这样

  1. 我不必有这么多重复的代码和
  2. 确保所有 BaseClass 对象都有SetFoo

你不能这样做:

    public abstract static BaseClass SetFoo;

因为静态的东西不可能是抽象的。 你也不能这样做:

    public static BaseClass SetFoo => new BaseClass{ Foo = false };

因为你不能新建一个抽象类。

但是,您可以做的是使用泛型来指定您想要的派生类型。 那看起来像这样:

void Main()
{
    ChildClassA cA = BaseClass.SetFoo<ChildClassA>();
}

public abstract class BaseClass
{
    public bool Foo {get; set;}
    
    public static T SetFoo<T>() where T:BaseClass, new() => new T{Foo = false };
}

public class ChildClassA : BaseClass
{
    // You can leave this here if you still want to call ChildClassA.SetFoo();
    //public static ChildClassA SetFoo() => new ChildClassA{Foo = false};
}

public class ChildClassB : BaseClass
{
    //Again, you can leave this for ChildClassB.SetFoo()--the compiler won't mind
    //public static ChildClassB SetFoo() => new ChildClassB { Foo = false };
}

这只是比我们真正想要的(派生.StaticBase)稍微笨重一点,但它非常接近。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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