操作会破坏运行时的稳定性吗? [英] Operation could destabilize the runtime?

查看:28
本文介绍了操作会破坏运行时的稳定性吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm having a little bit of trouble understanding what the problem is here. I have a bit of code that pulls records from a database using LINQ and puts them into an object which is cast into an interface. It looks a bit like this:

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

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

When I test this, I put the returned IEnumerable into a variable called results and run this line:

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

运行时,我收到 System.Security.VerificationException:操作可能会破坏运行时的稳定性."

When this is run, I get a System.Security.VerificationException: "Operation could destabilize the runtime."

我找到了解决方案 这里,这是:

I found the solution here, which is this:

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

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

This works, but I'm having trouble understanding what's happening here. Why did I get the exception in the first place and how did the lines of code above fix it? The MSDN documentation seems to suggest that this is an issue of type safety, but I'm not seeing where the previous code was type-unsafe.

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

UPDATE A little bit more information I found out. The first example works if I make the return type IQueryable. This sheds a little bit more light on what was going wrong, but I'm still confused about the why. Why didn't the compiler force me to cast the IEnumerable into an IQueryable?

推荐答案

我相信这是一个协变或逆变的问题,正如 此论坛帖子.

I believe it is an issue of covariance or contravariance as noted by this forum post.

参见 C# 中的协方差和逆变,第二部分:数组协方差协方差和逆变系列.

虽然他在我链接的文章中处理数组,但我相信这里也存在类似的问题.在您的第一个示例中,您将返回一个 IEnumerable,其中可能包含实现比 ISomeTable更大的接口的对象(即 - 您可以将当 IEnumerable 只能包含长颈鹿时,海龟变成动物 IEnumerable).我认为当您返回 IQueryable 时它起作用的原因是因为它比您可以返回的任何内容更大/更宽,因此您可以保证返回的内容将能够处理(?).

Although he is dealing with Arrays in the article I linked, I believe a similar problem presents itself here. With your first example, you are returning an IEnumerable that could contain objects that implement an interface that is larger than ISomeTable (i.e. - you could put a Turtle into an Animals IEnumerable when that IEnumerable can only contain Giraffes). I think the reason it works when you return IQueryable is because that is larger/wider than anything you could return, so you're guaranteed that what you return you will be able to handle(?).

在第二个示例中,OfType 确保返回的内容是一个存储所有必要信息的对象,只返回那些可以转换为 Giraffe 的元素.

In the second example, OfType is ensuring that what gets returned is an object that stores all the information necessary to return only those elements that can be cast to Giraffe.

我很确定它与上面概述的类型安全问题有关,但正如 Eric Lippert 所说 高阶函数伤害了我的大脑,我有无法准确表达为什么这是一个协变/逆变问题.

I'm pretty sure it has something to do with the issues of type safety outlined above, but as Eric Lippert says Higher Order Functions Hurt My Brain and I am having trouble expressing precisely why this is a co/contravariant issue.

这篇关于操作会破坏运行时的稳定性吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆