c# - 操作可能会破坏运行时的稳定性?

标签 c# .net linq linq-to-sql .net-3.5

我有点难以理解这里的问题所在。我有一些代码使用 LINQ 从数据库中提取记录并将它们放入一个对象中,该对象被转换为一个接口(interface)。它看起来有点像这样:

public IEnumerable<ISomeObject> query()
{
    return from a in dc.SomeTable
           select new SomeObject
           {
             //Assign various members here
           } as ISomeObject;
}

当我对此进行测试时,我将返回的 IEnumerable 放入一个名为 results 的变量中并运行以下行:

Assert.AreEqual(EXPECTED_COUNT, results.Count());

当它运行时,我得到一个 System.Security.VerificationException:“Operation could destabilize the runtime.”

我找到了解决方案 here , 这是这样的:

var results = from a in dc.SomeTable
              select new SomeObject
              {
                //Assign various members here
              } as ISomeTable;
return results.OfType<ISomeObject>();

这行得通,但我无法理解这里发生的事情。为什么我一开始会得到异常,上面的代码行是如何修复它的? MSDN 文档似乎暗示这是一个类型安全问题,但我没有看到以前的代码在哪里类型不安全。

更新 我发现了更多信息。如果我将返回类型设置为 IQueryable,则第一个示例有效。这更清楚地说明了什么出了问题,但我仍然对原因感到困惑。为什么编译器不强制我将 IEnumerable 转换为 IQueryable?

最佳答案

我认为这是 this forum post 指出的协变或逆变问题.

参见 Covariance and Contravariance in C#, Part Two: Array Covariance和其余的Covariance and Contravariance series在 Eric Lippert 的博客上。

虽然他在我链接的文章中处理数组,但我相信这里也会出现类似的问题。对于您的第一个示例,您将返回一个 IEnumerable,它可能包含实现一个大于 ISomeTable 的接口(interface)的对象(即 - 您可以将当 IEnumerable 只能包含长颈鹿时,将 Turtle 转换为 Animals IEnumerable)。我认为当你返回 IQueryable 时它起作用的原因是因为它比你可以返回的任何东西都更大/更宽,所以你保证你返回的东西你将能够处理(?)。

在第二个例子中,OfType确保返回的是一个对象,该对象存储仅返回那些可以转换为 Giraffe 的元素所需的所有信息。

我很确定它与上面概述的类型安全问题有关,但正如 Eric Lippert 所说 Higher Order Functions Hurt My Brain我无法准确表达为什么这是一个协变/逆变问题。

关于c# - 操作可能会破坏运行时的稳定性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/378895/

相关文章:

c# - 在查询中使用输出参数的 .NET LINQ 调用方法并使用输出值

c# - 使用 Web API 过滤

c# - FileStream 和创建文件夹

c# - 使用 c# 调用数据库时出现 System.String ToString() 错误

.NET:GC 何时运行?内存泄漏?

c# - IoC 和构造函数过度注入(inject)反模式解决方案

c# - Linq GroupBy 和多列

c# - 创建动态优惠券检查器

c# - 在表单中输入的数据不会插入到数据表中

.net - vs2008 代理?