集合上的隐式转换

本文关键字:转换 集合 | 更新日期: 2023-09-27 17:58:38

本周我遇到了一个关于C#对集合的隐式转换的问题。虽然这(使用implicit)可能不是我们的最终方法,但我希望至少完成代码,为团队提供一个选项。我将问题归结为以下示例:

在我的示例中,我有两个类:一个表示业务对象(Foo),另一个表示该业务项(FooVO)的客户端版本(View object),定义如下。。。

public class Foo
{
    public string Id {get; set;}
    public string BusinessInfo {get; set;}
}
public class FooVO
{
    public string Id {get; set;}
    public static implicit operator FooVO( Foo foo )
    {
        return new FooVO { Id = foo.Id };
    }
}

我的问题是,当我有一个Foo对象列表,并想使用隐式运算符将它们转换为FooVO对象列表时。

List<Foo> foos = GetListOfBusinessFoos(); // Get business objects to convert

我试过

List<FooVO> fooVOs = foos; // ERROR

List<FooVO> fooVOs = (List<FooVO>) foos; // ERROR

甚至

List<FooVO> fooVOs = foos.Select( x => x ); // ERROR

我知道我可以在一个循环中做到这一点,但我希望有一种简单的(LINQ?)方法可以在一次拍摄中转换对象。有什么想法吗?

提前谢谢。

编辑修复了示例中的拼写错误

集合上的隐式转换

SO上几乎每天都会有这样的问题被问到。你不能这样做,因为这样做违反了类型安全:

List<Giraffe> g = new List<Giraffe>();
List<Animal> a = g; // Should this be legal?
a.Add(new Tiger()); // Nope; we just added a tiger to a list of giraffes.

在C#4.0中,您可以隐式地从IEnumerable<Giraffe>转换为IEnumerable<Animal>,因为没有"Add"方法来搞砸事情。但是,如果元素类型的转换是用户定义的,就永远不能进行这样的"协变"转换。它必须是引用身份转换。

您需要创建第二个列表,然后一次复制一个列表。或者使用LINQ辅助方法(如Select和ToList)为您完成这项工作。

您想要的类型系统概念的名称是"协方差";协变关系是一种你认为"长颈鹿是动物,所以长颈鹿的序列是动物的序列"的关系。如果你对这个主题感兴趣,那么你可以在这里阅读我们如何将协方差(和反方差)添加到C#4.0中:

http://blogs.msdn.com/b/ericlippert/archive/tags/covariance+和+contrasvariance/default.aspx

从底部开始。

您的示例不起作用的原因是您试图将IEnumerable<FooVO>分配给List<FooVO>。以下内容应该有效。

 List<FooVO> fooVos = foos.Select<Foo,FooVO>(x => x).ToList();
List<FooVO> d = new List<FooVO>(foos.Select(x => (FooVO)x)); 

适用于我。

使用传入static implicit operator FooVO( Foo foo )的ConvertAll方法作为参数

List<FooVO> fooVOs = foos.ConvertAll<FooVO>(FooVO.FooVO);