簡體   English   中英

包含c#中列表的動態類型

[英]Dynamic type with lists in c#

我有一點問題。

我想這樣做:

Type[] classes = new Type[]{ Class1, Class2 };

foreach(Type t in classes){   
  List<t> list = new List<t>(); 
}

有辦法做到這一點嗎?

不能在運行時轉換為泛型類型,因為泛型中的類型需要在編譯時解析。

可以使用反射以動態方式創建泛型類型,但除非您對強制轉換進行硬編碼,否則您獲得的所有內容都是對象。

我不能真正說出你想要的是什么,我不得不同意這是一個XY問題 我傾向於做出這樣一種冒昧的陳述:這是一個設計問題,它試圖解決,而不是直接解決設計問題,或者詢問你想要直接實現的問題。


您可以使用以下代碼創建類型,然后dynamic類型可用於在不知道/關心它是列表或T是什么的情況下對List<T>的各種成員進行類型化

using System;
using System.Collections.Generic;

namespace ConsoleApplication61
{
    class Program
    {
        static void Main(string[] args)
        {
            dynamic o = CreateGeneric(typeof(List<>), typeof(int));
            o.Add(1);
            Console.WriteLine(o[0]);
            Console.Read();
        }

        public static object CreateGeneric(Type generic, Type innerType, params object[] args)
        {
            System.Type specificType = generic.MakeGenericType(new System.Type[] { innerType });
            return Activator.CreateInstance(specificType, args);
        }
    }
}

上面的示例duck類型是Add方法和Indexer。 DLR在運行時執行類型處理和鴨子類型 - 例如,知道1int

只是為了澄清,我可能不會在生產中使用這樣的代碼(除非你的要求非常具體需要這個),並且任何類型不匹配的問題都會在運行時發生; 因此您需要非常准確地鍵入(有限的IntelliSense)或具有良好的錯誤處理。

感謝這篇關於CreateGeneric方法的博客文章

這假定.NET 4具有新的CLR。 正如@MartinLiversage也指出的那樣,這個特定的示例假設您以強類型的方式使用列表。 在我的例子中,我將一個int傳遞給dynamic隱藏的List<int>


自從它發布以來,我們一直在使用.NET 4。 我們有一個大型應用程序,具有更大的代碼庫。 dynamic在應用程序中不使用一次,在測試代碼庫中只使用幾次。 這並不是說“不要使用它”,而是說“大多數時候,你不需要它”。

你可以這樣做:

foreach(Type t in classes)
{
   var listType = typeof(List<>).MakeGenericType(t);
   var instance = Activator.CreateInstance(listType);
}

這可以使用Type.MakeGenericType方法

這是一個我發現應該適用於ya的漂亮方法: CodeRef

public static object CreateGeneric(Type generic, Type innerType, params object[] args)
{
    System.Type specificType = generic.MakeGenericType(new System.Type[] { innerType });
    return Activator.CreateInstance(specificType, args);
}

並像這樣使用它:

var o = CreateGeneric(typeof(List<>), t);

不幸的是,要添加項目,您必須這樣做(其中item是您要添加的項目)。

MethodInfo addMethod = o.GetType().GetMethod("Add");
addMethod.Invoke(o, new object[] { item.ToType(t) });

或者使用另一個答案中提到的Generic類型。

你可以試試這個:

Type[] classes = new Type[] { typeof(A), typeof(B) };           
foreach (Type t in classes)
{
     Type genericType = typeof(List<>).MakeGenericType(t);
     var list = Activator.CreateInstance(genericType);
}

如果你想在一個列表中保留對象,那么它們可能有一些共同之處。

在這種情況下,我認為,就像評論中提到的LB一樣,你在這里提出了一個錯誤的問題。

可能這是你的設計問題。 考慮一下這些類型,看看它們有什么共同點,並考慮從一種基本類型派生,或者兩者都實現相同的接口。 在這種情況下,您將能夠實例化基本類型/接口的對象列表並使用它們。

只是為了給你一個良好的開端:

    abstract class Vehicle {
        public int NumberOfWheels { get; set; }
    }

    class Car : Vehicle
    {
        public Car()
        {
            NumberOfWheels = 4;
        }
    }

    class Bicycle : Vehicle
    {
        public Bicycle()
        {
            NumberOfWheels = 2;
        }
    }

    static void Main(string[] args)
    {

        var v1 = new Car();
        var v2 = new Bicycle();

        var list = new List<Vehicle>();
        list.Add(v1);
        list.Add(v2);

        foreach (var v in list)
        {
            Console.WriteLine(v.NumberOfWheels);
        }

        Console.ReadKey();
    }

暫無
暫無

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

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