簡體   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