在第220页,C#语言规范5.0版说:
这很重要以确保查询表达式的结果永远不会是源对象本身,因为这将向查询的客户端揭示源的类型和标识。
为什么向查询的客户端揭示源的类型和标识会有问题?
例如,from c in customers select c
形式的查询表达式转换为customers.Select(c => c)
,而不仅仅是customers
。
在上面的例子中,在我看来,将customers
返回给客户端和返回customers.Select(c => c)
的结果一样好。为什么不呢?
2条答案
按热度按时间yqkkidmi1#
尽管Robert McKee的回答是合理的,并且提出了一个有趣的观点,但这实际上并不是我们在编写规范的那一部分时所考虑的主要问题。我们实际上想到的问题是这样的:
假设你手里有一个
C
。你能写出这段代码吗?列表中的查询的存在不应该授予获得查询的代码更改列表的能力!它应该授予代码执行查询的权利,仅此而已。
现在想象一下,查询实际上 Package 了一个数据库调用,而不是
List<int>
。如果调用者可以从查询中获得底层数据库,那么他们也许可以对该数据库进行查询或编辑,而查询的作者并不希望他们这样做。当然,LINQ并不是设计成一个安全系统,如果它是您抵御想要攻击数据库的代码的唯一防线,那么您可能非常容易受到攻击。但是,所有的安全系统工作得更好时,他们的组件使用良好的“防御深度”。永远不泄漏查询所查询的集合是防御策略的一部分。
有关此功能的更多信息,请参阅我关于此主题的文章:
https://web.archive.org/web/20150905090133/http://blogs.msdn.com/b/ericlippert/archive/2008/05/12/trivial-projections-are-usually-optimized-away.aspx
jxct1oxe2#
可能是因为它会打破这样的东西:
如果源代码可能沿着链泄漏,而不是使用抽象模型,那么对数据进行抽象就变得更加困难。如果查询可能会根据您在查询本身中使用的参数更改其类型,则不能真正使用
var data
。