简体   繁体   English

C# 将数组转换为泛型 T List<>

[英]C# Convert array to generic T List<>

I'm trying to convert an array (object[]) to a generic type T where T is a List<>我正在尝试将数组 (object[]) 转换为泛型类型 T,其中 T 是一个 List<>

The issue here is that T is the type of the list and not the type of the items in the list.这里的问题是 T 是列表的类型,而不是列表中项目的类型。 So we can't just create a List.所以我们不能只创建一个列表。

While I could serialize the array and deserialize it into a generic T, I don't want to use this option and would favor a faster approach to the problem.虽然我可以序列化数组并将其反序列化为通用 T,但我不想使用此选项,而是希望采用更快的方法来解决问题。

Below is the code to test and reproduce the issue.下面是测试和重现问题的代码。

public T ConvertList<T>(object obj)
{

    if (obj is object[] objects)
    {
        var type = objects.GetType().GetElementType();
        var list = objects.Select(o => Convert.ChangeType(o, type)).ToList();

        // Unable to cast object of type 'System.Collections.Generic.List`1[System.Object]' to type 'System.Collections.Generic.List`1[System.String]'.'
        return (T)(object)list;
    }

    return default;

}

var list = ConvertList<List<string>>( new []{ "1", "a", "b" });
Assert.AreEqual(typeof(List<string>), list.GetType());

The issue here is that we cannot do something like:这里的问题是我们不能做类似的事情:

var list = new List<typeof(type)>()

I'm open to suggestions on how we can achieve something like this.我愿意听取有关如何实现这样的目标的建议。

Thanks.谢谢。

To solve this problem we can use the fact that generic class List<TElement> implements non-generic interface IList .为了解决这个问题,我们可以利用泛型 class List<TElement>实现非泛型接口IList的事实。 Here is how we can use this fact to solve your problem:以下是我们如何利用这一事实来解决您的问题:

public T ConvertList<T>(object obj)
{
    if (obj is object[] objects)
    {
        // Here we create an instance of type T, where T is actually a generic
        // List<TElement>. Then we cast it to type IList. Therefore here we don't 
        // have to know and specify the type of the elements of List<TElement>.
        IList list = (IList) Activator.CreateInstance(typeof(T));

        foreach (object o in objects)
            // Here we call IList.Add(object o). Internally it casts added
            // elements to the actual type of the elements of List<TElement>.
            list.Add(o);

        return (T) list;
    }

    return default;
}

Here is complete sample that shows this approach.这是显示此方法的完整示例

To use this approach you should ensure that a correct type of the List<TElement> is specified when calling method ConvertList<T> .要使用此方法,您应该确保在调用方法ConvertList<T>时指定了正确类型的List<TElement> >。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM