{"id":2606,"date":"2008-03-18T12:33:00","date_gmt":"2008-03-18T12:33:00","guid":{"rendered":"https:\/\/test.simple-talk.com\/uncategorized\/anonymous-delegates-rock\/"},"modified":"2016-07-28T10:49:16","modified_gmt":"2016-07-28T10:49:16","slug":"anonymous-delegates-rock","status":"publish","type":"post","link":"https:\/\/www.red-gate.com\/simple-talk\/blogs\/anonymous-delegates-rock\/","title":{"rendered":"Anonymous delegates rock"},"content":{"rendered":"<p>I&#8217;m finding I really like C#&#8217;s anonymous delegates. I&#8217;ve used them several times now in various ways. Normal delegates are already a Good Thing, however basically they are C(++) function pointers with a much nicer syntax. Anonymous delegates do clever things like having the ability to access local variables.&#160; This just provides some syntactic sugar and the compiler under the hood creates classes to hold the variables and puts the anonymous method on that class.&#160; Take a look with a decompiler and you can see what gets generated.<\/p>\n<p>One &#8220;obvious&#8221; pattern I&#8217;ve seen people here come up with independently is to invoke something on a worker thread from a UI thread, or the other way round (and sometimes both by nesting one delegate inside another). <\/p>\n<p>However another use I like is what I want to share today. <\/p>\n<p>I&#8217;ve been using WMI a bit recently. WMI can be used (amongst other things) to get information about remote computers.&#160; I won&#8217;t go into the detail here &#8211; there&#8217;s plenty on the web about it (http:\/\/en.wikipedia.org\/wiki\/Windows_Management_Instrumentation).&#160; I may even do a blog myself on it one day.<\/p>\n<p>To access WMI via .NET you use the System.Management namespace.&#160; There are various ways to call and get the information, but a common example is to run a query in a SQL-esque way &#8211; e.g. &#8220;select TotalPhysicalMemory&#160; from Win32_ComputerSystem&#8221; will get you the total physical memory on a machine.&#160; However to run a query like this requires quite verbose code, not least because a lot of objects you create need Dispose()ing of afterwards.<\/p>\n<p><code><br \/>ManagementScope&#160;scope&#160;=&#160;new&#160;ManagementScope(&#160;\"\\\\mymachinename\\root\\cimv2\"&#160;); <br \/>scope.Connect(); <br \/>objQry&#160;=&#160;new&#160;ObjectQuery(&#160;\"select&#160;TotalPhysicalMemory&#160;from&#160;Win32_ComputerSystem\"&#160;); <br \/>UInt64&#160;totalMemory&#160;=&#160;0; <br \/>using(&#160;ManagementObjectSearcher&#160;searcher&#160;=&#160;new&#160;ManagementObjectSearcher(&#160;scope,&#160; <br \/>{ <br \/>&#160;&#160;&#160;&#160;using(&#160;ManagementObjectCollection&#160;collection&#160;=&#160;searcher.Get()&#160;) <br \/>&#160;&#160;&#160;&#160;{ <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;foreach(&#160;ManagementObject&#160;obj&#160;in&#160;collection&#160;) <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;{ <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;totalMemory&#160;=&#160;(UInt64)obj[\"TotalMemory\"]; <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;obj.Dispose(); <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;} <br \/>&#160;&#160;&#160;&#160;} <br \/>} <br \/><\/code><br \/>So great &#8211; i&#8217;ve got that out, but I want to find out how much free disk it has as well.&#160; This query is &#8220;select Name,FreeSpace from Win32_LogicalDisk where DriveType=3&#8221; and could well return me more than one disk. (DriveType=3 means physical disks on this machine as opposed to mapped network drives etc.)<\/p>\n<p>I can reuse the scope so the extra code is&#8230;<\/p>\n<p><code>objQry&#160;=&#160;new&#160;ObjectQuery(&#160;\"select&#160;Name,FreeSpace&#160;from&#160;Win32_LogicalDisk&#160;where&#160;DriveType=3\"&#160;); <br \/>Dictionary&lt;string,UInt64&gt;&#160;drives&#160;=&#160;new&#160;Dictionary&lt;string,UInt64&gt;(); <br \/>using(&#160;ManagementObjectSearcher&#160;searcher&#160;=&#160;new&#160;ManagementObjectSearcher(&#160;scope,&#160; <br \/>{ <br \/>&#160;&#160;&#160;&#160;using(&#160;ManagementObjectCollection&#160;collection&#160;=&#160;searcher.Get()&#160;) <br \/>&#160;&#160;&#160;&#160;{ <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;foreach(&#160;ManagementObject&#160;obj&#160;in&#160;collection&#160;) <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;{ <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;drives.add(&#160;(string)obj[\"Name\"],&#160;(UInt64)obj[\"FreeSpace\"]&#160;); <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;obj.Dispose(); <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;} <br \/>&#160;&#160;&#160;&#160;} <br \/>} <br \/><\/code><br \/>But that instantly offends me &#8211; I have 13 lines of code, of which 10 are the same as above.&#160; That&#8217;s 10 lines repeated whenever I want to run another query.<\/p>\n<p>Instead I can define a method like this:<\/p>\n<p><code>private&#160;delegate&#160;void&#160;UseManagementObject(&#160;ManagementObject&#160;obj&#160;); <\/p>\n<p>private&#160;static&#160;void&#160;DoWmiQuery(&#160;ManagementScope&#160;scope,&#160;string&#160;qry,&#160;UseManagementObject&#160;callback&#160;) <br \/>{ <br \/>&#160;&#160;&#160;&#160;ObjectQuery&#160;objQry&#160;=&#160;new&#160;ObjectQuery(&#160;qry&#160;);&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160; <br \/>&#160;&#160;&#160;&#160;using(&#160;ManagementObjectSearcher&#160;searcher&#160;=&#160;new&#160;ManagementObjectSearcher(&#160;scope,&#160;objQry&#160;)&#160;) <br \/>&#160;&#160;&#160;&#160;{ <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;using(&#160;ManagementObjectCollection&#160;collection&#160;=&#160;searcher.Get()&#160;) <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;{ <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;foreach(&#160;ManagementObject&#160;obj&#160;in&#160;collection&#160;) <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;{ <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;callback(&#160;obj&#160;); <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;obj.Dispose(); <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;} <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;} <br \/>&#160;&#160;&#160;&#160;} <br \/>} <\/code><\/p>\n<p>Now I can reduce my 2 previous pieces to this:<\/p>\n<p><code>ManagementScope&#160;scope&#160;=&#160;new&#160;ManagementScope(&#160;\"\\\\mymachinename\\root\\cimv2\"&#160;); <br \/>scope.Connect(); <br \/>UInt64&#160;totalMemory&#160;=&#160;0; <br \/>DoWMiQuery(&#160;scope,&#160;\"select&#160;TotalPhysicalMemory&#160;from&#160;Win32_ComputerSystem\",&#160;delegate(&#160;ManagementObject&#160;obj&#160;) <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;{ <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;totalMemory&#160;=&#160;(UInt64)obj[\"TotalMemory\"]; <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;}&#160;); <\/p>\n<p>Dictionary&lt;string,UInt64&gt;&#160;drives&#160;=&#160;new&#160;Dictionary&lt;string,UInt64&gt;(); <br \/>DoWMiQuery(&#160;scope,&#160;\"select&#160;Name,FreeSpace&#160;from&#160;Win32_LogicalDisk&#160;where&#160;DriveType=3\",&#160;delegate(&#160;ManagementObject&#160;obj&#160;) <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;{ <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;drives.add(&#160;(string)obj[\"Name\"],&#160;(UInt64)obj[\"FreeSpace\"]&#160;); <br \/>&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;&#160;}&#160;); <\/p>\n<p><\/code>Jobs a good&#8217;un \ud83d\ude42  <\/p>\n","protected":false},"excerpt":{"rendered":"<p>I&#8217;m finding I really like C#&#8217;s anonymous delegates. I&#8217;ve used them several times now in various ways. Normal delegates are already a Good Thing, however basically they are C(++) function pointers with a much nicer syntax. Anonymous delegates do clever things like having the ability to access local variables.&#160; This just provides some syntactic sugar&#8230;&hellip;<\/p>\n","protected":false},"author":143472,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[2],"tags":[],"coauthors":[],"class_list":["post-2606","post","type-post","status-publish","format-standard","hentry","category-blogs"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/2606","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/users\/143472"}],"replies":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/comments?post=2606"}],"version-history":[{"count":2,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/2606\/revisions"}],"predecessor-version":[{"id":41610,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/2606\/revisions\/41610"}],"wp:attachment":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/media?parent=2606"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/categories?post=2606"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/tags?post=2606"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/coauthors?post=2606"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}