
{"id":792,"date":"2011-02-04T01:00:21","date_gmt":"2011-02-04T06:00:21","guid":{"rendered":"http:\/\/www.ikriv.com\/blog\/?p=792"},"modified":"2011-02-04T01:00:21","modified_gmt":"2011-02-04T06:00:21","slug":"ienumerable-lazy-and-dangerous","status":"publish","type":"post","link":"https:\/\/ikriv.com\/blog\/?p=792","title":{"rendered":"IEnumerable: lazy and dangerous"},"content":{"rendered":"<p>Time and time again I am burnt by the same bug.<\/p>\n<p>There are two kinds of enumerables in .NET: enumerators and generators. Enumerators go over some collection and return its items. Enumerator will always return the same values, no matter how many times you iterate over it. This only changes when someone adds or removes items from the collection.<\/p>\n<p>Generators, on the other hand, compute new values every time. They may or may not be the same, depending on how the generator is built and what happened around it. All those neat LINQ methods like &#8220;where&#8221; and &#8220;select&#8221; are in fact generators.<\/p>\n<p>For example,<\/p>\n<pre><code>IEnumerable&lt;string&gt names = new[] { \"Paris\", \"Berlin\", \"London\" }; \/\/ enumerator\nIEnumerable&lt;City&gt cities = names.Select(name=>new City(name)); \/\/ generator<\/code><\/pre>\n<p>Every time time you do <code>foreach (var city in cities)<\/code> a different set of cities is produced. E.g.<\/p>\n<pre><code>foreach (var city in cities) city.Visited = true;\n...\nforeach (var citiy in cities)\n{\n    Console.WriteLine(city.Visited); \/\/ prints false\n}<\/code><\/pre>\n<p>One can easily convert a generator to an enumerator by adding <code>ToList()<\/code>, <code>ToArray()<\/code>, or <code>ToDictionary()<\/code>. This will create a &#8220;real&#8221; data structure that is not modified.<\/p>\n<pre><code>var cityList = names.Select(name=>new City(name))<font color=\"red\"><b>.ToList();<\/b><\/font>\nforeach (var city in cityList) city.Visited = true;\n...\nforeach (var citiy in cityList)\n{\n    Console.WriteLine(city.Visited); \/\/ prints true\n}<\/code><\/pre>\n<p>Even more subtle issues can occur when using conditions:<\/p>\n<p><code><\/p>\n<pre>cityList[0].Visited = true;\nvar visitedCities = cityList.Where(city=>city.Visited);\nConsole.WriteLine( visitedCities.Count() ); \/\/ 1\n...\ncityList[0].Visited = false;\nConsole.WriteLine( visitedCities.Count() ); \/\/ 0<\/pre>\n<p><\/code><\/p>\n<p>This is an obvious case of hidden dependency. We modified something inside cityList, but it &#8220;magically&#8221; affects similarly unrelated <code>visitedCities<\/code>. Hidden dependencies are evil, because they are, well, hidden, and people tend to forget about them.<\/p>\n<p>The most annoying part is that generators and enumerators look exactly the same, and it may be quite difficult, or even impossible to tell whether particular <code>IEnumerable<\/code> is a generator or an enumerator. Functional style programming assumes read-only objects, so it does not matter, but throwing in any modifiable state creates a dangerous mix.<\/p>\n<p>It does not mean one should not use <code>IEnumerable<\/code> in stateful scenarios, but it is better to be careful, you have been warned! <a style=\"display:none\" href=\"http:\/\/www.codeproject.com\/script\/Articles\/BlogFeedList.aspx?amid=1181663\" rel=\"tag\">CodeProject<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Time and time again I am burnt by the same bug. There are two kinds of enumerables in .NET: enumerators and generators. Enumerators go over some collection and return its <a href=\"https:\/\/ikriv.com\/blog\/?p=792\" class=\"more-link\">[&hellip;]<\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"Layout":"","footnotes":""},"categories":[8,4],"tags":[],"class_list":["entry","author-ikriv","post-792","post","type-post","status-publish","format-standard","category-cs","category-hack"],"_links":{"self":[{"href":"https:\/\/ikriv.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/792","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/ikriv.com\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/ikriv.com\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/ikriv.com\/blog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/ikriv.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=792"}],"version-history":[{"count":0,"href":"https:\/\/ikriv.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/792\/revisions"}],"wp:attachment":[{"href":"https:\/\/ikriv.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=792"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/ikriv.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=792"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/ikriv.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=792"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}