簡體   English   中英

C#泛型:任何方式將泛型參數類型稱為集合?

[英]C# generics: any way to refer to the generic parameter types as a collection?

我需要編寫一堆采用1..N泛型類型參數的方法,例如:

int Foo<T1>();
int Foo<T1,T2>();
int Foo<T1,T2,T3>();
...
int Foo<T1,T2,T3...TN>();

Foo()里面,我想為每種類型做一些事情,例如

int Foo<T1,T2,T3>() {
    this.data = new byte[3]; // allocate 1 array slot per type
}

有沒有辦法參數化這個,所以我不編輯Foo()每個變體,類似於:

int Foo<T1,T2,T3>() {
    this.data = new byte[_NUMBER_OF_GENERIC_PARAMETERS];
}

理想情況下,我也希望能夠獲得一個數組或類型的集合:

int Foo<T1,T2,T3>() {
    this.data = new byte[_NUMBER_OF_GENERIC_PARAMETERS];

    // can do this
    Type [] types = new Type[] { T1, T2, T3 };
    // but would rather do this
    Type [] types = _ARRAY_OR_COLLECTION_OF_THE_GENERIC_PARAMETERS;
}

您可以從MethodInfo.GetGenericArguments數組中讀取當前通用參數及其編號。

您可以使用MethodBase.GetCurrentMethod方法檢索當前方法的MethodInfo

請注意,由於C#和CLI不支持可變參數通用參數列表,因此仍需要使用不同數量的通用參數提供方法的幾個泛型重載。

因此,具有三個通用參數的方法的代碼示例可以這樣寫:

int Foo<T1,T2,T3>() {
    MethodInfo mInfo = (MethodInfo)MethodBase.GetCurrentMethod();
    Type[] types = mInfo.GetGenericArguments();

    this.data = new byte[types.Length];
}

1)您可以通過反射獲取模板參數的數量: http//msdn.microsoft.com/en-us/library/system.reflection.methodbase.getcurrentmethod.aspx 這樣,您就可以為每個Foo實現通用實現。 在每個Foo中你可以打電話:

FooImpl();

唯一的區別(關於“GetCurrentMethod”)是你需要獲取前一個方法的方法信息:

StackTrace stackTrace = new StackTrace();
MethodBase methodBase = stackTrace.GetFrame(1).GetMethod();

2)您可以在運行時生成所有Foo版本 - 所有版本都將共享調用FooImpl的相同實現。 有關在運行時生成方法的一些細節:在運行時動態創建函數 ,請訪問: http//msdn.microsoft.com/en-us/library/exczf7b9.aspx

.NET框架將具有N類型參數的泛型類或方法視為具有與具有更多或更少的名稱不同的名稱。 如果沒有對框架進行大的改動就可以安排事情以便調用函數

foo<T>(autogeneric ref T it)

如:

foo(1, "George", 5.7);

將被翻譯為:

struct foo99 {public int p1; public string p2; public double p3};
...
foo99 temp99;
temp99.p1 = 1;
temp99.p2 = "George";
temp99.p3 = 5.7;
foo1(ref temp);

這將允許通用方法有效地接受任意數量的參數。 能夠通過ref傳遞這樣的匿名結構可能看起來並不十分有用,但是當與lambdas結合使用時它可能非常強大。

通常,關閉lambda表達式中的局部變量需要將局部變量提升到堆對象並構建一個以該堆對象為目標的委托。 如果可以使用上述樣式,則可以代替創建持久閉包對象和委托並傳遞委托,只需將適當的變量提升到結構並將一個byref與靜態委托一起傳遞給它。 這只適用於被調用的例程不必持久傳遞閉包的情況,但在另一方面,調用者會知道被調用的例程不會持久化閉包。 此外,雖然沒有.NET語言會支持這樣的事情,並且可能需要進行一些框架更改以允許執行此操作的代碼是易變的,通過引用傳遞一個結構,其中一些成員也是byrefs可以使lambda可以訪問封閉過程的ref參數 - 目前不可能的(因為不能保證創建的委托不會比創建它的范圍更長)。 結構在它們所處的范圍死亡時死亡,因此問題不一定存在。

我希望.NET語言有一種表達這些概念的便捷方式。 閉包可以導致變量的生命周期被任意持久化的事實意味着在閉包中曾經使用過變量的代碼必須假設外部代碼可以隨時改變它。 基於結構的方法不會有這個問題。

不能。您不能根據需要使用Type參數。 但你可以使用像Tuple這樣的東西。 它允許你包裝泛型。 但是你不能使用TypeParamter本身。

暫無
暫無

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

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