skip to Main Content

Is this a Visual Studio bug or .NET runtime bug?

Consider the following code:

 public class DoWork
{
    public void Run()
    {
        List<Entity> items = new List<Entity>();
        items.Add(new Entity { Name = "1" });
        items.Add(new Entity { Name = "12" });
      
        int maxLength = items.Max(p => p.Name.Length);
        var temp = items.Where(p => p.Name.Length == maxLength);

        do
        {
            this.Import(items);

            temp = items.Where(p => p.Name.Length < maxLength && !p.IsImported);
            // If you use a quick watch, you will see just one item correctly

            maxLength = temp.Count() > 0 ? temp.Max(p => p.Name.Length) : 0;
            // Here, when you set maxLength, you will notice that VS will break into lambda body above

            // Here temp is empty, but if you use the final ToList it works:
            // temp = items.Where(p => p.Name.Length < maxLength && !p.IsImported).ToList(); 

        }
        while (maxLength > 0);
    }

    private void Import(List<Entity> items)
    {
        items.Last().IsImported = true;
    }
}

It’s a strange behavior and it’s the first time I see something like that.
Is it a bug?

2

Answers


  1. No it’s not a bug – temp is just a query that does not get executed until you actually use it. So when you do:

    maxLength = temp.Count() > 0 ? temp.Max(p => p.Name.Length) : 0;
    

    The query actually gets executed twice. If you want to run the full query you could do:

    temp = items.Where(p => p.Name.Length < maxLength && !p.IsImported).ToList();
    

    But since you are looping and running multiple similar queries it’s not completely clear if running the queries twice is actually a problem.

    Login or Signup to reply.
  2. The statement temp = items.Where(...) only sets up a query but does not evaluate it; however, both Count() and Max() will. Note that temp is not a collection!

    You could use this instead to enumerate the list only once:

    maxLength = temp.DefaultIfEmpty().Max(p => p?.Name.Length ?? 0);
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search