在第220页,C#语言规范版本5.0说:
确保查询表达式的结果永远不是源对象本身是很重要的,因为它会向查询客户端显示源的类型和标识。
为什么向查询客户端显示源的类型和标识会有问题?
例如,from c in customers select c
形式的查询表达式转换为customers.Select(c => c)
而不仅仅是customers
。
在上述情况下,在我看来,向客户端返回customers
与返回customers.Select(c => c)
的结果一样好。为什么不呢?
答案 0 :(得分:8)
虽然罗伯特麦基的回答是合理的,并提出了一个有趣的观点,但实际上,在编写规范的这一部分时,这并不是我们想到的主要问题。我们实际想到的问题是:
class C
{
private List<int> myList = new List<int>();
// Only the code in C can add items to the list.
public IEnumerable<int> Items
{
get
{
return from item in myList select item;
}
}
}
假设您手头有C
。你能写这段代码吗?
((List<int>)c.Items).Add(123);
列表上存在查询不应该授予获取查询的代码更改列表的能力!它应该授予该代码执行查询的权利,而不是更多。
现在想象一下,查询实际上是包装数据库调用而不是List<int>
。如果调用者可以从查询中获取底层数据库,那么他们可能会对该数据库进行查询或编辑,而查询的作者并不打算这样做。
当然,LINQ并不是一个安全系统,如果它是你想要攻击数据库的代码的唯一防线,你可能很容易受到攻击。但是当所有安全系统的组件使用良好的“纵深防御”时,它们的工作效果更好永远不会泄漏查询正在查询的集合是防御策略的一部分。
有关此功能的更多信息,请参阅我关于此主题的文章: