繁体   English   中英

从泛型抽象类调用静态方法而不指定类型

[英]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.

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