集合的隐式转换
本周我遇到了关于集合中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 foos = GetListOfBusinessFoos(); // Get business objects to convert
我试过了
List fooVOs = foos; // ERROR
和
List fooVOs = (List) foos; // ERROR
乃至
List fooVOs = foos.Select( x => x ); // ERROR
我知道我可以在循环中执行此操作,但我希望能够直接(LINQ?)方式一次转换对象。 有任何想法吗?
先感谢您。
编辑修复了示例中的拼写错误
几乎每天都会问这样一个问题。 你不能这样做,因为这样做违反了类型安全:
List g = new List (); List 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
转换为IEnumerable
因为没有“添加”方法来搞砸了。 但是,如果元素类型的转换是用户定义的 ,那么你永远不能进行“协变”转换。 它必须是参考或身份转换。
您需要创建第二个列表并一次复制一个列表。 或者使用像Select和ToList这样的LINQ辅助方法为您完成这项工作。
你想要的类型系统概念的名称是“协方差”; 一个协变关系就是你推理“长颈鹿是动物因此长颈鹿的序列是动物序列”的关系。 如果您对此主题感兴趣,那么您可以在此处阅读我们如何在C#4.0中添加协方差(和逆变):
http://blogs.msdn.com/b/ericlippert/archive/tags/covariance+and+contravariance/default.aspx
从底部开始。
您的示例不起作用的原因是您尝试将IEnumerable
分配给List
。 以下应该有效。
List fooVos = foos.Select(x => x).ToList();
List d = new List (foos.Select(x => (FooVO)x));
适合我。
使用ConvertAll方法传递static implicit operator FooVO( Foo foo )
作为参数
List fooVOs = foos.ConvertAll (FooVO.FooVO);