Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>For the <a href="http://en.wikipedia.org/wiki/Closure_%28computer_science%29" rel="noreferrer">exact definition, I suggest looking at its Wikipedia entry</a>. It's especially good. I just want to clarify it with an example.</p> <p>Assume this C# code snippet (that's supposed to perform an <code>AND</code> search in a list):</p> <pre><code>List&lt;string&gt; list = new List&lt;string&gt; { "hello world", "goodbye world" }; IEnumerable&lt;string&gt; filteredList = list; var keywords = new [] { "hello", "world" }; foreach (var keyword in keywords) filteredList = filteredList.Where(item =&gt; item.Contains(keyword)); foreach (var s in filteredList) // closure is called here Console.WriteLine(s); </code></pre> <p>It's a common pitfall in C# to do something like that. If you look at the lambda expression inside <code>Where</code>, you'll see that it defines a function that it's behavior depends on the value of a variable at its definition site. It's like passing a <em>variable itself</em> to the function, rather than the <em>value of that variable</em>. Effectively, when this closure is called, it retrieves the value of <code>keyword</code> variable at that time. The result of this sample is very interesting. It prints out <strong>both</strong> "hello world" and "goodbye world", which is not what we wanted. What happened? As I said above, the function we declared with the lambda expression is <strong>a closure over <code>keyword</code> <em>variable</em></strong> so this is what happens:</p> <pre><code>filteredList = filteredList.Where(item =&gt; item.Contains(keyword)) .Where(item =&gt; item.Contains(keyword)); </code></pre> <p>and at the time of closure execution, <code>keyword</code> has the value "world," so we're basically filtering the list a couple times with the same keyword. The solution is:</p> <pre><code>foreach (var keyword in keywords) { var temporaryVariable = keyword; filteredList = filteredList.Where(item =&gt; item.Contains(temporaryVariable)); } </code></pre> <p>Since <code>temporaryVariable</code> is scoped to the <strong>body</strong> of the <code>foreach</code> loop, in every iteration, it is a different variable. In effect, each closure will bind to a distinct variable (those are different instances of <code>temporaryVariable</code> at each iteration). This time, it'll give the correct results ("hello world"):</p> <pre><code>filteredList = filteredList.Where(item =&gt; item.Contains(temporaryVariable_1)) .Where(item =&gt; item.Contains(temporaryVariable_2)); </code></pre> <p>in which <code>temporaryVariable_1</code> has the value of "hello" and <code>temporaryVariable_2</code> has the value "world" at the time of closure execution. </p> <p>Note that the closures have caused an extension to the lifetime of variables (their life were supposed to end after each iteration of the loop). This is also an important side effect of closures. </p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload