将IList转换为SomeType[]

4

我有一个类型为List的集合,我想将其转换为SomeType[]。SomeType在运行时之前是未知的。

必须使用以下过程的签名来完成此操作。

private object ConvertListToArray(IList  collection)
{
       // This does not work since SomeType is not known before runtime.
       var convertedList = collection.Cast<SomeType>().ToArray();
        return convertedList;
}

请注意,集合是IList类型,但它的具体类型是已知的。
     List<SomeType>

返回集合必须是SomeType[]类型的对象。
如何做到呢?

那么 collection.ToArray() 怎么样?这个能行吗? - Katalonis
你会如何期望代码能够识别出需要 SomeType[] 而不是 object[]String[] 或者 SomeOtherType[]?如果集合中包含了 SomeTypeSeomOtherType,你会期望什么结果?如果集合为空呢? - Jon Skeet
Katalonis - ToArray() 是 List<T> 的扩展方法,但我只有 IList。 - Oyvind
Jon Skeet - 具体列表是一种通用列表,只有一种类型。但是在转换时,我只有IList。 - Oyvind
4个回答

1
您可以通过以下实现来完成此操作:
class Program
{
    static void Main(string[] args)
    {
        // same type
        var myCollection = new List<string> {"Hello", "World"};
        var array = (string[])myCollection.ConvertToArray();
        Console.WriteLine(array[0]);

        // new type
        var intList = new List<int> {1, 2, 3};
        var stringArray = (string[])intList.ConvertToArray(typeof(string));
        Console.WriteLine(stringArray[0]);

        // mixed types
        var ouch = new List<object> {1, "Mamma", 3.0};
        var result= (string[])ouch.ConvertToArray(typeof(string));
        Console.WriteLine(result[0]);


    }
}

实施:

public static class ListExtensions
{
    public static object ConvertToArray(this IList collection)
    {
        // guess type
        Type type;
        if (collection.GetType().IsGenericType && collection.GetType().GetGenericArguments().Length == 0)
            type = collection.GetType().GetGenericArguments()[0];
        else if (collection.Count > 0)
            type = collection[0].GetType();
        else
            throw new NotSupportedException("Failed to identify collection type for: " + collection.GetType());

        var array = (object[])Array.CreateInstance(type, collection.Count);
        for (int i = 0; i < array.Length; ++i)
            array[i] = collection[i];
        return array;
    }

    public static object ConvertToArray(this IList collection, Type arrayType)
    {
        var array = (object[])Array.CreateInstance(arrayType, collection.Count);
        for (int i = 0; i < array.Length; ++i)
        {
            var obj = collection[i];

            // if it's not castable, try to convert it
            if (!arrayType.IsInstanceOfType(obj))
                obj = Convert.ChangeType(obj, arrayType);

            array[i] = obj;
        }

        return array;
    }
}

1
我认为他说SomeType在编译时是未知的。 - sloth
@BigYellowCactus:我还用更多动态代码更新了示例。 - jgauffin
非常感谢,这个很好用。为了使它更通用,我使用了以下代码:var array1 = list.ConvertToArray(list.GetType().GetGenericArguments()[0]); - Oyvind
我想点赞,但我的声望低于15,所以我不能投票。 - Oyvind

1
public static class ListExtensions
{
    public static T[] ConvertToArray<T>(IList list)
    {
        return list.Cast<T>().ToArray();
    }

    public static object[] ConvertToArrayRuntime(IList list, Type elementType)
    {
        var convertMethod = typeof(ListExtensions).GetMethod("ConvertToArray", BindingFlags.Static | BindingFlags.Public, null, new [] { typeof(IList)}, null);
        var genericMethod = convertMethod.MakeGenericMethod(elementType);
        return (object[])genericMethod.Invoke(null, new object[] {list});
    }

}
[TestFixture]
public class ExtensionTest
{
    [Test]
    public void TestThing()
    {
        IList list = new List<string>();
        list.Add("hello");
        list.Add("world");

        var myArray = ListExtensions.ConvertToArrayRuntime(list, typeof (string));
        Assert.IsTrue(myArray is string[]);
    }
}

谢谢,这个很好用。为了在任何列表中使用它,我使用了以下代码: var myArray = ListExtensions.ConvertToArrayRuntime(list, list.GetType().GetGenericArguments()[0]); - Oyvind
我想点赞,但我的声望低于15,所以我无法投票。 - Oyvind

0
我发布这篇文章是因为其他答案似乎有点冗长。我非常确定这个代码可以满足楼主的需求。它对我很有效。
public static Array ConvertToArray(ICollection collection, Type type)
{ 
    var array = Array.CreateInstance(type, collection.Count);

    collection.CopyTo(array, 0);

    return array;
}

0

你可以尝试:

   private T[] ConvertListToArray<T>(IList collection)
   {
   // This does not work since SomeType is not known before runtime.
            var convertedList = collection.Cast<T>().ToArray();
            return convertedList;
        }

问题是我在运行时没有 T。 - Oyvind
我不明白你的问题。如果在运行时仍然没有得到类型,我猜这是无法解决的。但是看到解决方案,我发现问题所在 :-) - Remco Bosman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接