我认为这可能是不可能的,但如果是,那就知道了。
我有一个静态维护它的子类实例的抽象类。我想在我的基类中实现一个静态getInstance()
方法,该方法将获取引用的任何类的实例。所以我需要一种方法来告诉静态调用中引用了哪个类。
我认为代码会更清楚:
abstract class Base
{
private static List<Base> allInstances;
public static List<Base> AllInstances
{
get {
if(allInstances==null)
{
// Implementation not relevant and not included to avoid clutter
}
return allInstances;
}
}
public static Base getInstance()
{
Type callingType = // This is what I am trying to fill in
if(callingType == typeof(Base))
throw new InvalidOperationException("Cannot get instance of Base class");
return AllInstances.Find(i => i.GetType() == callingType);
}
}
class A:Base { }
class B:Base { }
因此,如果我致电A.getInstance()
我的callingType
变量将为typeof(A)
。我的主要目标是避免在我的代码中调用Find
来使其更清晰,更易读,但我也很好奇,如果可能的话。
答案 0 :(得分:1)
C#不支持虚拟静态方法。
一种解决方法是使用GetInstance()
的通用方法。呼叫者不会呼叫A.GetInstance()
,而是呼叫Base.GetInstance<A>()
。然而,效果是一样的:
abstract class Base
{
...
public static T getInstance<T>() where T : Base
{
Type callingType = typeof(T);
// no need to check type; T will always be a type of or derived from Base
return AllInstances.Find(i => i.GetType() == callingType) as T;
}
}
虽然它会涉及一些样板文件,但您可以(如果您选择)在派生类级别编写便捷方法以获得相同的效果:
class A:Base
{
public static A getInstance() {return Base.getInstance<A>();}
}
class B:Base
{
public static B getInstance() {return Base.getInstance<B>();}
}
答案 1 :(得分:1)
不继承静态方法。他们是他们班级的范围。你写它的方式在A或B上没有“getInstance”方法......只在Base上。因此,通过您的方法,您尝试做的事情是不可能的。
但是,您可以使用通用方法:
public static T GetInstance<T>() where T : Base {
return (T)AllInstances.Find(i => i.GetType() == typeof(T));
}
然后你可以只请求像这样的类型的实例
var a = Base.GetInstance<A>();
var b = Base.GetInstance<B>();
和
一样简单var a = A.getInstance();
var b = B.getInstance();
因为类型T仅限于继承base(通过T:Base)的类型,所以你不必担心其他类型的类,因为它甚至不会编译:
var x = Base.GetInstance<SomeOtherRandomClass>();
答案 2 :(得分:1)
扩展我上面的评论,如果不将代码放在所有派生类中,你就无法真正做到。部分原因是,虽然您可以访问A.getInstance()
和B.getInstance()
,但它们都会被编译到调用Base.getInstance()
。参见IL的简单方法,例如:
public static void CallGetInstance()
{
var a = A.getInstance();
var b = B.getInstance();
Console.WriteLine(a == b);
}
编译为:
.method private hidebysig static
void CallGetInstance () cil managed
{
// Method begins at RVA 0x2054
// Code size 24 (0x18)
.maxstack 2
.locals init (
[0] class TestIL.Base a,
[1] class TestIL.Base b
)
IL_0000: nop
IL_0001: call class TestIL.Base TestIL.Base::getInstance()
IL_0006: stloc.0
IL_0007: call class TestIL.Base TestIL.Base::getInstance()
IL_000c: stloc.1
IL_000d: ldloc.0
IL_000e: ldloc.1
IL_000f: ceq
IL_0011: call void [mscorlib]System.Console::WriteLine(bool)
IL_0016: nop
IL_0017: ret
} // end of method Program::CallGetInstance
请注意,没有提到A.getInstance
或B.getInstance
。事实上,他们并不存在于IL中。由于StackFrame
和A.getInstance()
的IL中没有方法,因此B.getInstance()
和非常有用的技巧会有所帮助。
其他答案使用每个派生类调用的泛型方法提出了一种解决方法。这就像它将要获得的一样简单。