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