[英]Call static method from generic abstract class without specifying a type
我有一个像这样的抽象类:
public abstract class BaseCamera<TCamera> : ICamera where TCamera : ManagedCameraBase
{
public static uint GetNumberOfCameras()
{
using (var bus = new ManagedBusManager())
{
bus.RescanBus();
return bus.GetNumOfCameras();
}
}
}
并想这样称呼它: BaseCamera.GetNumberOfCameras()
这对我来说很有意义,因为既然这是一个抽象类,则只有具体的子类必须选择TCamera
,而基类则想获取所有摄像机的数量,无论它们是什么类型。
但是,编译器不赞成:
使用通用类型'BaseCamera'需要1个类型参数。
有没有解决的办法,还是我需要为此创建一个新类?
我认为值得指出的是ManagedCameraBase
是我包装的外部API中的类。 因此,我不想在对BaseCamera
任何调用中都包含它,这就是为什么我试图避免指定类型的原因。
因为这是一个抽象类,所以只有具体的子类才能选择
TCamera
这不是泛型的工作方式。 这与abstract
类毫无关系。 如果该类是泛型而不是抽象的,则仍需要指定泛型参数才能调用该类的静态方法。 最重要的是,还有什么可说的,一个子类也不能通用。 您的碰巧可能并非如此,但没有任何必要。
现在,在您的特殊情况下, GetNumberOfCameras
方法根本不使用通用参数( T
),因此无论您提供哪种通用参数都可以,您可以放入所需的任何内容,这样就可以正常工作。 当然,因此,有迹象表明该方法可能不属于此类。 它可能应该在该类还使用的另一个类中。
这是问题所在。 静态方法GetNumberOfCameras
属于包含它的类,但是对于每个类型,泛型类实际上被编译为单独的类。 因此,例如,如果您有以下内容:
public class Foo<T>
{
static int foo = 0;
public static void IncrementFoo()
{
foo++;
}
public static int GetFoo()
{
return foo;
}
}
然后您这样做:
Foo<string>.IncrementFoo();
Console.WriteLine(Foo<string>.GetFoo());
Console.WriteLine(Foo<int>.GetFoo());
您将看到对GetFoo
的第一个调用将返回一个,而第二个调用将返回零。 Foo<string>.GetFoo()
和Foo<int>.GetFoo()
是两个单独的静态方法 ,它们属于两个不同的类 (并访问两个不同的字段)。 这就是为什么您需要一种类型。 否则,编译器将不知道要调用哪个类的哪个静态方法。
您需要一个非泛型基类,以供您的泛型类继承。 因此,如果您这样做:
public class Foo<T> : Foo
{
}
public class Foo
{
static int foo = 0;
public static void IncrementFoo()
{
foo++;
}
public static int GetFoo()
{
return foo;
}
}
然后这样:
Foo<string>.IncrementFoo();
Console.WriteLine(Foo<string>.GetFoo());
Console.WriteLine(Foo<int>.GetFoo());
首先会给您您可能期望的。 换句话说,两次调用GetFoo
都将返回相同的结果。 而且,当然,您实际上不再需要类型参数,而可以这样做:
Foo.IncrementFoo();
或者,当然,如果没有理由不应该将静态方法作为BaseCamera
一部分,则可以将其移动到完全不同的类中
好吧,这里有几件事您需要更好地理解。
首先,我发现您的设计存在问题。 您尝试加入此类的方法实际上与该类的一般性质无关。 实际上,您正在实例化另一个类来完成这项工作,因此它实际上根本不属于这里。
如果它实际上与从ManagedCameraBase继承的对象有关,则该方法可能不必是静态的,而应是实例方法。 然后,您可以根据使用情况决定访问器(公共/私有)。
最后,您需要了解泛型在幕后的实际操作。 当您将通用库用于特定类型时,编译器会在后台为您创建基础专用类型。 如果要使用静态方法,则编译器将需要知道您要定位的类型,以便创建将为您的调用服务的静态实例。 因此,如果调用静态方法,则必须传递一个类型,并且最终将获得与调用该类型所使用的类型一样多的静态实例(当然,这些类型必须派生自ManagedCameraBase)。
如您所见,您应该将该方法移到某个助手类或类似的类中,或者使其成为非静态实例方法。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.