linq 为什么不向客户透露来源的类型和身份?

hjqgdpho  于 2023-10-13  发布在  其他
关注(0)|答案(2)|浏览(137)

在第220页,C#语言规范5.0版说:
这很重要以确保查询表达式的结果永远不会是源对象本身,因为这将向查询的客户端揭示源的类型和标识。
为什么向查询的客户端揭示源的类型和标识会有问题?
例如,from c in customers select c形式的查询表达式转换为customers.Select(c => c),而不仅仅是customers
在上面的例子中,在我看来,将customers返回给客户端和返回customers.Select(c => c)的结果一样好。为什么不呢?

yqkkidmi

yqkkidmi1#

尽管Robert McKee的回答是合理的,并且提出了一个有趣的观点,但这实际上并不是我们在编写规范的那一部分时所考虑的主要问题。我们实际上想到的问题是这样的:

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);

列表中的查询的存在不应该授予获得查询的代码更改列表的能力!它应该授予代码执行查询的权利,仅此而已。
现在想象一下,查询实际上 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

jxct1oxe

jxct1oxe2#

可能是因为它会打破这样的东西:

var data=(from c in customers select c);
if (something)
  data=data.Where(somethingelse);

如果源代码可能沿着链泄漏,而不是使用抽象模型,那么对数据进行抽象就变得更加困难。如果查询可能会根据您在查询本身中使用的参数更改其类型,则不能真正使用var data

相关问题