簡體   English   中英

使用約束泛型類型的靜態方法C#

[英]using static methods of a constrained generic type C#

我有一個通用類:

public class Foo<T> where T: Interface
{

}

T被強制實現的接口有2個靜態方法。

在構造函數中,我希望能夠基本上執行以下操作:

public Foo()
{
   value1 = T.staticmethod1();
   value2 = T.staticmethod2();
}

使用我上面發布的偽代碼無法實現這一點。 是不是可以用這種方式調用這些靜態方法?

您可以使用擴展方法。 這種技術被命名為偽混合 雖然擴展方法實際上是靜態的,但它們“假裝”為實例方法,因此您仍然需要T的具體實例。

此外,如果您希望您的界面保留其作為自我記錄“合同”的角色,這是一種作弊,它指定了您的T類應具有的方法。 但是它們是類型安全的(如果你沒有在范圍內引入IBarExtensions,你的Foo類將無法編譯)

//our interface
public interface IBar {}

// the two static methods are define as extension methods
public static class IBarExtensions {
    public static string someMethod1(this IBar self) {
        return "my initialization 1";
    }
    public static string someMethod2(this IBar self) {
        return "my initialization 2";
    }
}

public class Foo<T> where T : IBar, new()
{
    public string value1 {get; private set;}
    public string value2 {get; private set;}

    public Foo() {
        T t = new T(); // we can do this because of the "new()" constraint
                           // in the class definition
                           // Alternatively we could pass an instance of T in
                           // the constructor 
                           // public Foo(T t)
        value1 = t.someMethod1();
        value2 = t.someMethod2();       
    }
}

測試

public class TestBar : IBar {}
void Main()
{
    var c = new TestBar();

    var t = new Foo<TestBar>();
    Console.WriteLine(t.value1);
}

不,這是不可能的。 甚至沒有dynamic 通用的約束(如接口),但僅適用於實例成員。 您可以考慮將這些方法作為Func<T> / Action<T>委托傳遞給(參數)嗎?

除此之外,你唯一的(也是不受歡迎的)選擇就是反思。 或者更好:重新思考我們的方法。

C#不允許您調用接口中定義的靜態方法。 它發出一個命名不佳的錯誤消息:

如果您使用以允許接口中的靜態成員的語言編寫的庫,並且您嘗試從C#訪問靜態成員,也會發生CS0017。

如果C#允許它,你將使用接口名稱而不是通用參數名稱來調用它們:

// doesn't work:
public Foo() {
  value1 = Interface.staticmethod1();
  value2 = Interface.staticmethod2(); 
} 

所以,你有幾個選擇:

  1. 使用允許調用這些成員的語言(我認為 VB.NET和C ++ / CLI允許這樣做)。 您可以編寫一個可以在C#中使用的小適配墊片;
  2. 詢問為您提供此界面的人(可能甚至是您)在界面中不使用靜態成員。 它們可以移動到單獨的靜態類。 該類甚至可以嵌套在接口中(如果語言允許),它將在C#中工作。

不可能使用約束泛型類型參數的靜態成員,因為特定類型中靜態成員的存在不會說明派生類型是否具有具有該名稱的兼容成員。 假設類型“Foo”具有返回Int32的靜態函數Wowzo(),類型DerivedFoo1具有不同的靜態函數Wowzo(),它還返回Int32,類型DerivedFoo2(源自Foo),具有靜態成員Wowzo()返回一個String,類型DerivedFoo3有一個名為Wowzo的嵌套類。 如果T是一個被限制為Foo后代的類型參數,那么T.Wowzo是什么?

您還可以使用非靜態方法作為調用靜態方法的包裝器。 然后,非靜態方法可以成為您的界面的一部分。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM