【问题标题】:How do I create a dynamic type List<T>如何创建动态类型 List<T>
【发布时间】:2012-03-25 13:14:45
【问题描述】:

我不希望我的列表是固定类型的。相反,我希望 List 的创建取决于变量的类型。此代码不起作用:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections.Generic;
namespace ConsoleApplication3
{
    class Program
    {
        static void Main(string[] args)
        {

            string something = "Apple";

            Type type = something.GetType();

            List<type> list = null;

            Console.ReadKey();

        }
    }
}

谁能告诉我我需要做哪些更改才能使其正常工作?我希望 list 的创建取决于变量 something 的类型

【问题讨论】:

  • 您需要为此使用反射。您不能使用静态类型的变量。或者找到不同的方法。
  • “我想要类型安全,但我需要动态类型安全。”你能详细说明一下吗?
  • @David:动态类型安全我的意思是,如果变量 something 是 int 类型,则列表应该是 int 类型,如果是 string 类型,那么列表应该是 string 类型和等等。
  • @Jaggu 我不明白那是什么意思。你所说的似乎与类型安全无关。当您将错误类型的项目添加到列表中时,您是否正在寻找运行时错误?是这个意思吗?
  • @David:是的,运行时错误在这种情况下就足够了。没有编译错误就OK了。

标签: c# .net reflection


【解决方案1】:
string something = "Apple";
Type type = something.GetType();
Type listType = typeof(List<>).MakeGenericType(new [] { type } );
IList list = (IList)Activator.CreateInstance(listType);

这是创建静态未知类型列表的方式。但请注意,您无法静态提及列表的运行时类型。您必须使用非泛型类型甚至对象。

在不知道更多关于你想要完成的事情的情况下,这是你能做的最好的事情。

【讨论】:

  • 酷!除了ver需要var。
  • @Jaggu 不,var 不会像你想的那样做。它不会给你一个类型为List&lt;Apple&gt; 的变量,因为var 是一个静态类型构造。
  • 这会对列表操作执行运行时类型检查吗?所以如果你尝试添加不是Apple类型的东西,会不会出现运行时错误?
  • 是的,当然。这是一个完全可用的通用列表实例。 C# 不像 Java 那样进行类型擦除。
  • 感谢您对我的教育。我怀疑这些运行时检查是@Jaggu 所说的动态类型安全
【解决方案2】:

我想要类型安全,但我需要动态类型安全。

如果你的意思是你想要运行时类型安全,你可以使用反射创建 List&lt;T&gt;(参见 usr 的答案)或 dynamic,然后将其视为非泛型 IList

使用dynamic,它看起来像这样:

static List<T> CreateListByExample<T>(T obj)
{
    return new List<T>();
}

…

object something = "Apple";

IList list = CreateListByExample((dynamic)something);

list.Add(something); // OK

list.Add(42);        // throws ArgumentException

【讨论】:

    【解决方案3】:

    动态和反射都可以正常工作 - 但在性能上有缺点 - 并且失去强类型,代码设计/清晰度等。
    即您应该始终尝试不使用它来解决问题 - 如果可以,您的代码允许...
    因此,并且(注意)(很大程度上)取决于您的特定代码,需要,
    您还可以使用“技巧”来“推断”类型并使其通用...

    class Program
    {
        static void Main(string[] args)
        {
            string something = "Apple";
            int test = 5;
            var list = something.GetList();
            var listint = test.GetList();
            Console.WriteLine(list.GetType());
        }
    }
    static class Extension
    {
        public static List<T> GetList<T>(this T value)
        {
            return new[] { value }.ToList();
        }
    }
    

    ...即如果您有一个变量的值并且在“进入”通用上下文之前,
    你可以使用扩展(这对这方面很有帮助), 让它为你推断类型和列表类型
    注意:不幸的是,这种“变通”并不总是成功,并且当您的代码“过于动态”时(我知道这不是太“精确”,但超出了范围)以及它是否取决于反射诱导类型等.
    即没有一个干净利落的解决方案,这只是一个例子,你需要付出一些汗水:)让它为你工作 - 例如。你可能需要一个包装类型在这里和那里,显然以这种方式创建一个列表可能不是你想要的等等。

    【讨论】:

      【解决方案4】:

      编译器必须在编译时知道泛型类型 T。所以不,你真的不能这样做。

      【讨论】:

      • 编译时不需要知道 T 的类型。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-07-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多