将IEnumerable<T>转换为IEnumerable<U>?

15
以下代码在编译时通过,但在运行时抛出异常。我想做的是将一个类 PersonWithAge 强制转换为 Person 类。我该如何做,有什么解决方法吗?
class Person
{
    public int Id { get; set; }
    public string Name { get; set; }
}

class PersonWithAge
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int Age { get; set; }
}

class Program
{
    static void Main(string[] args)
    {
        IEnumerable<PersonWithAge> pwa = new List<PersonWithAge>
        {
            new PersonWithAge {Id = 1, Name = "name1", Age = 23},
            new PersonWithAge {Id = 2, Name = "name2", Age = 32}
        };

        IEnumerable<Person> p = pwa.Cast<Person>();

        foreach (var i in p)
        {
            Console.WriteLine(i.Name);
        }
    }
}

编辑: 顺便说一下,PersonWithAge将始终包含与Person相同的属性以及更多的属性。

编辑2: 抱歉各位,我应该让这个问题更清晰一些,假设我在数据库中有两个视图,其包含相同的列,但是第二个视图包含一个额外的字段。我的模型视图实体是由模拟数据库视图的工具生成的。我有一个MVC部分视图从一个类实体继承,但我有多种方法来获取数据...

不确定这是否有帮助,这意味着我无法使personWithAge继承自person。

6个回答

21

你不能强制类型转换,因为它们是不同的类型。你有两个选择:

1)更改类,使PersonWithAge从person继承。

class PersonWithAge : Person
{
        public int Age { get; set; }
}

2) 创建新对象:

IEnumerable<Person> p = pwa.Select(p => new Person { Id = p.Id, Name = p.Name });

9

使用 Select 代替 Cast 来指示如何执行从一种类型到另一种类型的转换:

IEnumerable<Person> p = pwa.Select(x => new Person { Id = x.Id, Name = x.Name });

由于PersonWithAge始终包含与Person相同的属性以及更多的属性,因此最好让它从Person继承。


5

你不能将两个不相关的类型强制转换成另一个。你可以通过让PersonWithAge继承自Person来实现将PersonWithAge转换为Person。由于PersonWithAge显然是Person的特殊情况,这是有充分道理的:

class Person
{
        public int Id { get; set; }
        public string Name { get; set; }
}

class PersonWithAge : Person
{
        // Id and Name are inherited from Person

        public int Age { get; set; }
}

如果你有一个名为personsWithAgeIEnumerable<PersonWithAge>,那么personsWithAge.Cast<Person>()就可以使用了。

在VS 2010中,你甚至可以完全跳过转换,直接使用(IEnumerable<Person>)personsWithAge,因为在.NET 4中IEnumerable<T>是协变的。


3
使PersonWithAge继承自Person。
就像这样:
class PersonWithAge : Person
{
        public int Age { get; set; }
}

1

你可能想要修改你的代码,使其类似于:

class Person
{
        public int Id { get; set; }
        public string Name { get; set; }
}

class PersonWithAge : Person
{
        public int Age { get; set; }
}

1
你可以保留 IEnumerable<PersonWithAge>,不需要将其转换为 IEnumerable<Person>。只需添加一个隐式转换,以在需要时将 PersonWithAge 对象转换为 Person
class Person
{
    public int Id { get; set; }
    public string Name { get; set; }
    public static implicit operator Person(PersonWithAge p)
    {
        return new Person() { Id = p.Id, Name = p.Name };
    }
}

List<PersonWithAge> pwa = new List<PersonWithAge>
Person p = pwa[0];

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