LINQ .Cast() 扩展方法失败,但 (type)object 有效
为了在某些 LINQ to SQL 对象和 DTO 之间进行转换,我们在 DTO 上创建了显式转换运算符。这样我们就可以执行以下操作:
DTOType MyDTO = (LinqToSQLType)MyLinq2SQLObj;
这效果很好。
但是,当您尝试使用 LINQ .Cast() 扩展方法进行转换时,它会引发无效的转换异常,指出无法将类型 Linq2SQLType 转换为类型 DTOType。即下面不起作用
List<DTO.Name> Names = dbContact.tNames.Cast<DTO.Name>()
.ToList();
但下面工作正常:
DAL.tName MyDalName = new DAL.tName();
DTO.Name MyDTOName = (DTO.Name)MyDalName;
并且下面也工作正常
List<DTO.Name> Names = dbContact.tNames.Select(name => (DTO.Name)name)
.ToList();
为什么 .Cast() 扩展方法会抛出无效的强制转换异常?我过去多次以这种方式使用 .Cast() 扩展方法,当您将基类型之类的东西转换为派生类型时,它工作得很好,但当对象具有显式转换运算符时,它就会崩溃。
To convert between some LINQ to SQL objects and DTOs we have created explicit cast operators on the DTOs. That way we can do the following:
DTOType MyDTO = (LinqToSQLType)MyLinq2SQLObj;
This works well.
However when you try to cast using the LINQ .Cast() extension method it trows an invalid cast exception saying cannot cast type Linq2SQLType to type DTOType. i.e. the below does not work
List<DTO.Name> Names = dbContact.tNames.Cast<DTO.Name>()
.ToList();
But the below works fine:
DAL.tName MyDalName = new DAL.tName();
DTO.Name MyDTOName = (DTO.Name)MyDalName;
and the below also works fine
List<DTO.Name> Names = dbContact.tNames.Select(name => (DTO.Name)name)
.ToList();
Why does the .Cast() extension method throw an invalid cast exception? I have used the .Cast() extension method in this way many times in the past and when you are casting something like a base type to a derived type it works fine, but falls over when the object has an explicit cast operator.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
Cast<>
扩展方法不应用用户定义的转换。它只能转换为接口或所提供类型的类层次结构内。用户定义的转换在编译时根据表达式中涉及的静态类型进行标识。它们不能用作运行时转换,因此以下内容是非法的:
无论 UDC 是否存在于 < code>SomeType 到
OtherType
- 它不能通过object
类型的引用来应用。尝试运行上述代码将在运行时失败,报告类似以下内容:Cast<>()
只能执行表示保留转换...这就是为什么您不能使用它来应用用户定义转换。Eric Lippert 有一篇关于行为的精彩文章C# 中的强制转换运算符 - 始终值得一读。
The
Cast<>
extension method does not apply user-defined conversions. It can only cast to interfaces or within the class heirarchy of the supplied type.User defined conversions are identified at compile time based on the static types involved in the expression. They cannot be applied as runtime conversions, so the following is illegal:
It doesn't matter whether a UDC exists from
SomeType
toOtherType
- it cannot be applied through a reference of typeobject
. Trying to run the above code would fail at runtime, reporting something like:Cast<>()
can only perform representation preserving conversions ... that's why you can't use it to apply user-defined conversions.Eric Lippert has a great article about the behavior of the cast operator in C# - always a worthwhile read.
如果反编译 Linq 程序集,您将得到类似于以下内容的代码。前面的答案是正确的,最终是从“对象”到目标类型的转换,这对于自定义类型总是失败。
特菲什
If you decompile the Linq assembly you get code resembling the following. The previous answer is correct, ultimately the cast is from 'object' to target-type which will always fail for custom types.
TFish
对于那些遇到这个问题并正在寻找解决方法的人...
不确定 C# 的确切语义,但我确信这非常简单。
For those that hit this question looking for a workaround...
Not sure the exact semantics with C#, but i'm sure it's pretty easy.