为什么没有strings.Cast <object>将List <string>转换为List <object>?</object> </string> </object>

时间:2009-12-02 17:21:48

标签: c# generics

this question中建议我可以将一个通用集合向上转换为.Cast<object>的对象集合。在reading up a bit on .Cast<>之后,我仍然无法将它作为通用集合转换为另一个通用集合。 以下为什么不起作用?

using System.Collections.Generic;
using System.Linq;
using System;

namespace TestCast2343
{
    class Program
    {
        static void Main(string[] args)
        {
            List<string> strings = new List<string> { "one", "two", "three" };

            //gives error: cannot convert from 'System.Collections.Generic.List<string>'
            //to 'System.Collections.Generic.List<object>'
            //IEnumerable<string> items = strings.Cast<object>();

            //this works
            strings.Cast<object>();

            //but they are still strings:
            foreach (var item in strings)
            {
                System.Console.WriteLine(item.GetType().Name);
            }

            //gives error: cannot convert from 'System.Collections.Generic.List<string>'
            //to 'System.Collections.Generic.List<object>'
            ProcessCollectionDynamicallyWithReflection(strings);

            Console.ReadLine();
        }

        static void ProcessCollectionDynamicallyWithReflection(List<object> items)
        {
            //...
        }
    }

}

答案:

谢谢你,里德,这是我开始工作的代码:

using System.Collections.Generic;
using System.Linq;
using System;

namespace TestCast2343
{
    class Program
    {
        static void Main(string[] args)
        {
            List<string> strings = new List<string> { "one", "two", "three" };
            List<int> ints = new List<int> { 34, 35, 36 };
            List<Customer> customers = Customer.GetCustomers();

            ProcessCollectionDynamicallyWithReflection(strings.Cast<object>().ToList());
            ProcessCollectionDynamicallyWithReflection(ints.Cast<object>().ToList());
            ProcessCollectionDynamicallyWithReflection(customers.Cast<object>().ToList());

            Console.ReadLine();
        }

        static void ProcessCollectionDynamicallyWithReflection(List<object> items)
        {
            foreach (var item in items)
            {
                Console.WriteLine(item.GetType().Name);
            }
        }
    }

    public class Customer
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public string Street { get; set; }
        public string Location { get; set; }
        public string ZipCode { get; set; }

        public static List<Customer> GetCustomers()
        {
            List<Customer> customers = new List<Customer>();
            customers.Add(new Customer { FirstName = "Jim", LastName = "Jones", ZipCode = "23434" });
            customers.Add(new Customer { FirstName = "Joe", LastName = "Adams", ZipCode = "12312" });
            customers.Add(new Customer { FirstName = "Jake", LastName = "Johnson", ZipCode = "23111" });
            customers.Add(new Customer { FirstName = "Angie", LastName = "Reckar", ZipCode = "54343" });
            customers.Add(new Customer { FirstName = "Jean", LastName = "Anderson", ZipCode = "16623" });
            return customers;
        }
    }
}

5 个答案:

答案 0 :(得分:11)

你在滥用Cast<T>

首先,在这里:

IEnumerable<string> items = strings.Cast<object>();

当您致电strings.Cast<object>()时,会返回IEnumerable<object>,而不是IEnumerable<string>。但是,集合中的项目仍然是字符串,但保留在对象的引用中。

稍后,当您想将此传递到一个List<object>的方法时,您需要将IEnumerable<T>变为IList<T>。这可以很容易地完成:

// Cast to IEnumerabe<object> then convert to List<object>
ProcessCollectionDynamicallyWithReflection(strings.Cast<object>().ToList());

答案 1 :(得分:2)

这是因为Cast<>方法不会返回List<T>类型,而是返回IEnumerable<T>。将.ToList调用添加到结尾,它将解决问题。

strings.Cast<object>().ToList();

答案 2 :(得分:1)

您还可以从另一个角度解决投射问题:修复ProcessCollectionDynamicallyWithReflection,因为它有不必要的限制:

private static void ShowItemTypes(IEnumerable items)
{
    foreach (object item in items)
    {
        string itemTypeName = (item != null) ? item.GetType().Name : "null";
        Console.WriteLine(itemTypeName);
    }
}

答案 3 :(得分:0)

这应该有效:

IEnumerable<object> items = strings.Cast<object>();

此外,如果没有强制转换,则无法将IEnumerable作为List传递给ProcessCollectionDynamicallyWithReflection。所以,这更好:

List<object> items = strings.Cast<object>().ToList();

答案 4 :(得分:0)

  

这个问题有人提出,   我可以投一个通用的集合   向上到一个对象的集合   .Cast<object>

不,这不正确。 Cast方法不会转换集合,它会转换集合中的每个项目,返回包含强制转换值的新集合。

您正在创建对象的集合,但是您只需将其丢弃,因为您没有将其分配给变量。 (嗯,你实际上丢弃了一个能够创建集合的表达式,但这并不是那么相关。)

您需要将集合分配给变量以保留它,并且当您需要List<object>时,您需要将演员项目放在列表中:

List<object> objects = strings.Cast<object>.ToList();

也许您应该考虑使用泛型而不是转换为对象:

static void ProcessCollectionDynamicallyWithReflection<T>(List<T> items)

通过这种方式,您可以在方法中编写强类型代码,并且您不必创建新集合只是为了能够将其发送到方法。