I had a strange bug i don’t understand, and changing LINQ’s IEnumerable to list half way through fixed it, and i dont understand why
Not Real the Code, but very similar
The code below doesn’t work:
// 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...
But when i change the ending to the following it works:
result = result.Reverse();
result = result.Concat(new List<PolicyResult> { thisNode });
var policyResults = result.ToList();
var firstPolicyResult = policyResults.First();
firstPolicyResult.OnNotAvailableNode = NodeProcessingActionEnum.ThrowException;
return policyResults;
All the types here are classes (reference types) except NodeProcessingActionEnum which is an enum.
Is this a bug?
Me missing something crucial about LINQ?
Help?
result.First()executes the (deferred / lazy) query.That line will set the value OK but when you use
resultlater the query will be executed again.Later you are looking at a newly fetched copy. The fact that it is different lets me assume that
GetAnsestors()is also lazily evaluated and is not an in memoryList<>This means that
ToList()is a worthwhile optimization as well as a fix. Note that after the ToList you can also use