简体   繁体   English

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

[英]Call static method from generic abstract class without specifying a type

I have an abstract class like this: 我有一个像这样的抽象类:

public abstract class BaseCamera<TCamera> : ICamera where TCamera : ManagedCameraBase
{
    public static uint GetNumberOfCameras()
    {
        using (var bus = new ManagedBusManager())
        {
            bus.RescanBus();
            return bus.GetNumOfCameras();
        }
    }
}

And want to call it like this: BaseCamera.GetNumberOfCameras() 并想这样称呼它: BaseCamera.GetNumberOfCameras()

It makes sense to me, because since this is an abstract class, only the concrete children classes must choose a TCamera , and the base class wants to get the number of all cameras, no matter they type. 这对我来说很有意义,因为既然这是一个抽象类,则只有具体的子类必须选择TCamera ,而基类则想获取所有摄像机的数量,无论它们是什么类型。

However, the compiler does not approve: 但是,编译器不赞成:

Using the Generic type 'BaseCamera' requires 1 type arguments. 使用通用类型'BaseCamera'需要1个类型参数。

Is there some way around it or do I need to create a new class just for this? 有没有解决的办法,还是我需要为此创建一个新类?

I think it is worth pointing out that ManagedCameraBase is a class from an external API I'm wrapping. 我认为值得指出的是ManagedCameraBase是我包装的外部API中的类。 Therefore, I do not want to include it in any of my calls for BaseCamera and that is why I'm trying to avoid specifying a type. 因此,我不想在对BaseCamera任何调用中都包含它,这就是为什么我试图避免指定类型的原因。

because since this is an abstract class, only the concrete children classes must choose a TCamera 因为这是一个抽象类,所以只有具体的子类才能选择TCamera

That's not how generics work. 这不是泛型的工作方式。 This has nothing at all to do with the class being abstract . 这与abstract类毫无关系。 If the class was generic and not abstract you would still need to specify a generic argument in order to call a static method of the class. 如果该类是泛型而不是抽象的,则需要指定泛型参数才能调用该类的静态方法。 On top of that, there's nothing to say that a child class can't also be generic. 最重要的是,还有什么可说的,一个子类不能通用。 Yours may happen to not be, but there's nothing requiring that to be the case. 您的碰巧可能并非如此,但没有任何必要。

Now, in your particular case, the GetNumberOfCameras method doesn't use the generic argument ( T ) at all, so it doesn't matter what generic argument you provide, you can put in whatever you want and it'll work just fine. 现在,在您的特殊情况下, GetNumberOfCameras方法根本不使用通用参数( T ),因此无论您提供哪种通用参数都可以,您可以放入所需的任何内容,这样就可以正常工作。 Of course, because of that, it's a sign that this method probably doesn't belong in this class; 当然,因此,有迹象表明该方法可能不属于此类。 it should probably be in another class that this class also uses. 它可能应该在该类还使用的另一个类中。

Here's the problem. 这是问题所在。 The static method GetNumberOfCameras belongs to the class that contains it, but a generic class actually gets compiled into separate classes for each type. 静态方法GetNumberOfCameras属于包含它的类,但是对于每个类型,泛型类实际上被编译为单独的类。 So, for example if you had this: 因此,例如,如果您有以下内容:

public class Foo<T>
{
    static int foo = 0;

    public static void IncrementFoo()
    {
        foo++;
    }

    public static int GetFoo()
    {
        return foo;
    }
}

And then you did this: 然后您这样做:

Foo<string>.IncrementFoo();
Console.WriteLine(Foo<string>.GetFoo());
Console.WriteLine(Foo<int>.GetFoo());

You will see that the first call to GetFoo will return one, but the second will return zero. 您将看到对GetFoo的第一个调用将返回一个,而第二个调用将返回零。 Foo<string>.GetFoo() and Foo<int>.GetFoo() are two separate static method that belong to two different classes (and access two different fields). Foo<string>.GetFoo()Foo<int>.GetFoo()两个单独的静态方法 ,它们属于两个不同的类 (并访问两个不同的字段)。 So that's why you need a type. 这就是为什么您需要一种类型。 Otherwise the compiler won't know which static method of which class to call. 否则,编译器将不知道要调用哪个类的哪个静态方法。

What you need is a non-generic base class for your generic class to inherit from. 您需要一个非泛型基类,以供您的泛型类继承。 So if you do this: 因此,如果您这样做:

public class Foo<T> : Foo
{

}

public class Foo
{
    static int foo = 0;

    public static void IncrementFoo()
    {
        foo++;
    }

    public static int GetFoo()
    {
        return foo;
    }
}

Then this: 然后这样:

Foo<string>.IncrementFoo();
Console.WriteLine(Foo<string>.GetFoo());
Console.WriteLine(Foo<int>.GetFoo());

Will give you what you might have expected at first. 首先会给您您可能期望的。 In other words, both calls to GetFoo will return the same result. 换句话说,两次调用GetFoo都将返回相同的结果。 And, of course, you don't actually need the type argument anymore and can just do: 而且,当然,您实际上不再需要类型参数,而可以这样做:

Foo.IncrementFoo();

Or course, the alternative is to just move your static methods into an entirely different class if there's no reason why it should be part of BaseCamera 或者,当然,如果没有理由不应该将静态方法作为BaseCamera一部分,则可以将其移动到完全不同的类中

Well, there are a couple of things here you need to understand better. 好吧,这里有几件事您需要更好地理解。

First of all, I see a problem with your design. 首先,我发现您的设计存在问题。 The method you are attempting to stick into this class really has nothing to do with the generic nature of it. 您尝试加入此类的方法实际上与该类的一般性质无关。 In fact, you are instantiating another class to do the job so it really does not belong here at all. 实际上,您正在实例化另一个类来完成这项工作,因此它实际上根本不属于这里。

If it actually had something to do with an object that inherits from ManagedCameraBase, the method would probably not need to be static but rather an instance method. 如果它实际上与从ManagedCameraBase继承的对象有关,则该方法可能不必是静态的,而应是实例方法。 You can then decide on the accessor (public/private) based on usage. 然后,您可以根据使用情况决定访问器(公共/私有)。

Finally, you need to understand what Generics actually do under the covers. 最后,您需要了解泛型在幕后的实际操作。 When you use the generic base with a particular type, an underlying specialized type is created for you behind the scenes by the compiler. 当您将通用库用于特定类型时,编译器会在后台为您创建基础专用类型。 If you were to use the static method, the compiler would need to know the type you are targeting in order to create the static instance that will serve your call. 如果要使用静态方法,则编译器将需要知道您要定位的类型,以便创建将为您的调用服务的静态实例。 Because of this, if you call the static method, you must pass a type and you will end up with as many static instances as the types you use to call it (the types must derive from ManagedCameraBase, of course). 因此,如果调用静态方法,则必须传递一个类型,并且最终将获得与调用该类型所使用的类型一样多的静态实例(当然,这些类型必须派生自ManagedCameraBase)。

As you can see, you should either move that method out to some helper class or something of the sort, or make it a non-static, instance method. 如您所见,您应该将该方法移到某个助手类或类似的类中,或者使其成为非静态实例方法。

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

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