簡體   English   中英

C#動態通用列表

[英]C# dynamic generic list

我想創建一個通用的List <>,其類型在運行時聲明。

我可以做到以下幾點,但由於它是動態的,我懷疑有速度懲罰。 我正在為異國情調的數據庫編寫一個包裝器,因此速度至關重要。

List<dynamic> gdb = new List<dynamic>()

我在動態泛型類型中閱讀了這篇文章 ,但無法讓它發揮作用。 具體來說,該對象不會顯示為List,因此沒有添加方法。

    Type ac;

    switch (trail[dataPos].Type)
    {
        case GlobalsSubscriptTypes.Int32:
            ac = typeof(System.Int32);

            break;
        case GlobalsSubscriptTypes.Int64:
            ac = typeof(System.Int64);

            break;

        default:
            ac = typeof(System.String);

            break;
    }

    var genericListType = typeof(List<>);
    var specificListType = genericListType.MakeGenericType(ac);
    var gdb = Activator.CreateInstance(specificListType);

如何讓gdb顯示為以下之一:

List<System.Int32>
List<System.Int64>
List<System.String>

一旦使用了Activator.CreateInstance ,就可以將結果轉換為適當的類型。 您可以使用IList例如:

var gdb = (IList)Activator.CreateInstance(specificListType);
gdb.Add(1);

請注意,如果您要添加的類型與泛型類型不匹配,則上面會拋出ArgumentException

哦, gdb 正確的類型。 由於您在運行時確定類型,因此編譯器不知道它。 因此,它是靜態類型為object ,並不顯示Add方法。 您有幾個選項可以解決這個問題:

  1. 將其轉換為正確的類型:

     switch (trail[dataPos].Type) { case GlobalsSubscriptTypes.Int32: ((List<int>) gdb).Add(...); break; ... default: ((List<String>) gdb).Add(...); break; } 
  2. 轉換為常見的超類型:

     ((System.Collections.IList) gdb).Add(...); 
  3. 使用動態調用:

     dynamic gdb = Activator.CreateInstance(specificListType); gdb.Add(...); 

在您的情況下, gdb將始終是System.Object ,因為CreateInstance返回任何類型的對象。

這里有幾個選項 - 您可以將其轉換為IList (非泛型),因為您知道List<T>實現此接口,並使用IList.Add

或者,您可以將其聲明為dynamic ,並使用動態綁定:

dynamic gdb = Activator.CreateInstance(specificListType);

這將使您編寫代碼,就好像它是相應類型的List<T> ,並且調用將在運行時通過動態綁定進行綁定。

List<dynamic>編譯與List<object>完全相同的類型,而不是類型化List<int>速度懲罰,例如,超過裝箱值類型。 但是如果你要向IList施放你仍然會有拳擊懲罰FYI。

你可能遇到麻煩的是調用Activator (一種反射方法),因為直接調用構造函數可能會慢得多。

這有什么關系嗎? 除非您實際運行配置文件,否則您將無法知道,因為它始終取決於您的實際使用情況。

我最好的客人,你真正想做的是:

IList gdb;

switch (trail[dataPos].Type)
{
    case GlobalsSubscriptTypes.Int32:
        gdb = new List<int>();
        break;
    case GlobalsSubscriptTypes.Int64:
        gdb = new List<long>();
        break;
    default:
        gdb = new List<string>();
        break;
}

此外,如果你真的需要在沒有拳擊的情況下進行操作,可以使用通用幫助方法完成所有工作:

switch (trail[dataPos].Type)
{
    case GlobalsSubscriptTypes.Int32:
        return Helper<int>(trail[dataPos]);
    case GlobalsSubscriptTypes.Int64:
        return Helper<long>(trail[dataPos]);
    default:
        return Helper<string>(trail[dataPos]);
}

暫無
暫無

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

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