【问题标题】:Bug in .Net's LINQ, or me missing something?.Net 的 LINQ 中的错误,还是我遗漏了什么?
【发布时间】:2012-03-22 10:39:34
【问题描述】:

我有一个奇怪的错误,我不明白,将 LINQ 的 IEnumerable 更改为中途修复它,我不明白为什么

不是真正的代码,但非常相似 下面的代码不起作用:

// an IEnumerable of some object (Clasess) internally an array
var ansestors = GetAnsestors();

            var current = GetCurrentServerNode();

            var result = from serverNode in ansestors
                         select new PolicyResult
                                    {
                                      //Some irrelevant stuff 
                                        OnNotAvailableNode = NodeProcessingActionEnum.ContinueExecution,
                                    };

            var thisNode = new PolicyResult
            {
                //Some irrelevant stuff 
                OnNotAvailableNode = NodeProcessingActionEnum.ThrowException,
            };

            result = result.Reverse();
            result = result.Concat(new List<PolicyResult> { thisNode });

            result.First().OnNotAvailableNode = NodeProcessingActionEnum.ThrowException;

            // When looking in the debugger, and in logs, the first element of the
            // result sequence has OnNotAvailableNode set to ContinueExecution
            // Which doesnt make any sense...

但是当我将结尾更改为以下内容时,它会起作用:

        result = result.Reverse();
        result = result.Concat(new List<PolicyResult> { thisNode });

        var policyResults = result.ToList();
        var firstPolicyResult = policyResults.First();

        firstPolicyResult.OnNotAvailableNode = NodeProcessingActionEnum.ThrowException;
        return policyResults;

这里的所有类型都是类(引用类型),除了 NodeProcessingActionEnum 是一个枚举。

这是一个错误吗?

我错过了一些关于 LINQ 的重要内容?

帮助?

【问题讨论】:

  • Reverse() 不返回 void 吗?你没有收到错误cannot convert void to .....
  • 他说代码不行……
  • @HenkHolterman 该行是从代码中复制粘贴的。 Enumerable.Reverse() 返回一个新的反向集合,它是原始集合的副本...
  • @AK_ 哎呀,谢谢,我还以为某处有 ToList

标签: c# .net linq


【解决方案1】:

result.First() 执行(延迟/延迟)查询。

该行将设置值 OK,但是当您稍后使用 result 时,查询将被执行再次

稍后您将查看新获取的副本。它不同的事实让我假设GetAnsestors() 也被延迟评估并且不是内存中的List&lt;&gt;

这意味着ToList() 是值得优化和修复的。请注意,在 ToList 之后您还可以使用

 var firstPolicyResult = policyResults[0];  

【讨论】:

  • 我认为你应该改写你的答案,如果其他人用谷歌搜索这个问题会更清楚。要说每次评估 LINQ IEnumerable 时,它​​都会执行第一个因式分解选择,并且 First() 和后面的枚举都对其进行评估。所以每个人都会看到不同的集合。
【解决方案2】:

问题是在您的 IEnumerable 上运行 First 会将其从枚举器中删除,因此您可以检查下一个元素。 实际上我已经改变了主意 - 可能不是这样。不过,这个解决方案可能值得一试。

您可以将 IEnumerable 包装为可以为您做出改变的东西,例如使用the Select override which accepts an index too:

var modifiedResults = results.Select((r, index) => {
    if (index == 0) {
        // This is the first element
        r.OnNotAvailableNode = NodeProcessingActionEnum.ThrowException;
    }
    return r;
});

(未经测试)应该可以解决问题。

【讨论】:

  • 我不明白你在说什么。为什么要在结果上调用 Firs() 来改变它?它的 IEnumerable 不是 IEnumerator...
猜你喜欢
  • 2022-01-22
  • 2012-02-07
  • 2012-01-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-23
  • 1970-01-01
相关资源
最近更新 更多