views:

904

answers:

5

Hello. I found something quite odd(I think!). If I try to put a breakpoint in the yes() method, it will never pause the program when it executes the function. If I try to do the same to any other line of code, it will work just as expected. Is it a bug, or is there something that's escaping me?

The filter will return the 2 objects, everything seems to be working as expected except the debugger.

private void Form1_Load(object sender, EventArgs e) {
    List<LOL> list = new List<LOL>();
    list.Add(new LOL());
    list.Add(new LOL());

    IEnumerable<LOL> filter = list.Where(
        delegate(LOL lol) {
            return lol.yes();
        }
    );

    string l = "";   <------this is hit by the debugger
}

class LOL {
    public bool yes() {
        bool ret = true; <---------this is NOT hit by the debugger
        return ret;
    }
}

Thanks

+13  A: 

Enumerable.Where is a lazy operator -- until you call something that goes through the IEnumerable returned by where (ie. calling .ToList() on it), your function won't get called.

Try changing your code to this and see if it gets called:

....
IEnumerable<LOL> filter = list.Where(
    delegate(LOL lol) {
        return lol.yes();
    }
).ToList();

string l = "";
Jonathan
+2  A: 

You have to materialize the list. Add a ...

filter.ToList();

... after the declaration and you will hit your breakpoint. About the best discussion I've seen on that is here. It does lazy evaluation much better justice than I could do.

JP Alioto
A: 

Thank you guys. That .ToList() thing did it!

Jorge Branco
Make sure that you understand *why* the ToList() thing did it, that is more important than simply fixing it. (As a side note, you can - and should - edit your original question and place this comment there.)
Groo
+2  A: 

As others have said, you have just defined your criteria but have not asked it for execution. This is called lazy loading (guys, correct me if I am wrong).

Run a foreach loop on filter to see what happens.

shahkalpesh
A: 

Jonathan is correct.

Try running this console application and set breakpoints where indicated to see it clearly.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            List<LOL> list = new List<LOL>();
            list.Add(new LOL());
            list.Add(new LOL());

            IEnumerable<LOL> filter = list.Where(
                delegate(LOL lol)
                {
                    return lol.yes();
                }
            );

            // Breakpoint #2 will not have been yet.
            Console.Write("No Breakpoint"); // Breakpoint #1 
            // (Breakpoint #2 will now be hit.)
            Console.Write("Breakpoint! " + filter.Count()); 
        }

        class LOL
        {
            public bool yes()
            {
                bool ret = true; // Breakpoint #2
                return ret;
            }

        }

    }
}
Colin Cochrane