我有一个这样的抽象类:
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
,并且基类想要获得所有相机的数量,无论它们是什么类型。
但是,编译器不批准:
使用Generic类型&#39; BaseCamera&#39;需要1种类型 参数。
是否有某种方法或我是否需要为此创建一个新类?
我认为值得指出的是ManagedCameraBase
是来自外部API的一个类。因此,我不想将其包含在BaseCamera
的任何调用中,这就是我尝试避免指定类型的原因。
答案 0 :(得分:3)
因为这是一个抽象类,所以只有具体的子类必须选择
TCamera
这不是泛型如何运作的。这与abstract
类没有任何关系。如果该类是通用的并且不是抽象,那么仍然需要指定一个泛型参数,以便调用该类的静态方法。最重要的是,没有什么可以说子类不能也是通用的。你可能不会这样,但没有什么要求是这样的。
现在,在您的特定情况下,GetNumberOfCameras
方法根本不使用泛型参数(T
),因此无关紧要什么是泛型参数你提供,你可以放入你想要的任何东西,它会工作得很好。当然,正因为如此,这表明这个方法可能不属于这个类;它可能应该在这个类也使用的另一个类中。
答案 1 :(得分:1)
这就是问题所在。静态方法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
的一部分
答案 2 :(得分:0)
嗯,这里有一些你需要更好地理解的东西。
首先,我发现您的设计存在问题。你试图坚持这个类的方法实际上与它的通用性质无关。实际上,你正在实例化另一个类来完成这项工作,所以它根本就不属于这里。
如果它实际上与从ManagedCameraBase继承的对象有关,则该方法可能不需要是静态的,而是实例方法。然后,您可以根据使用情况决定访问者(公共/私人)。
最后,您需要了解Generics实际上做了什么。当您使用具有特定类型的通用基础时,编译器会在幕后为您创建基础专用类型。如果您要使用静态方法,则编译器需要知道您要定位的类型,以便创建将为您的调用提供服务的静态实例。因此,如果调用静态方法,则必须传递一个类型,最终会得到与用于调用它的类型一样多的静态实例(当然,类型必须从ManagedCameraBase派生)。
正如您所看到的,您应该将该方法移动到某个帮助器类或类似的东西,或者使其成为非静态的实例方法。