{"id":103,"date":"2008-01-15T11:53:39","date_gmt":"2008-01-15T18:53:39","guid":{"rendered":"http:\/\/jameskovacs.com\/2008\/01\/15\/Syntactic+Sugar+Compiler+Candy+And+Other+Sweets"},"modified":"2008-01-15T11:53:39","modified_gmt":"2008-01-15T18:53:39","slug":"syntactic-sugar-compiler-candy-and-other-sweets","status":"publish","type":"post","link":"https:\/\/www.jameskovacs.com\/index.php\/2008\/01\/15\/syntactic-sugar-compiler-candy-and-other-sweets\/","title":{"rendered":"Syntactic Sugar, Compiler Candy, and Other Sweets"},"content":{"rendered":"<p>A great new feature of Visual Studio 2008 is multi-targeting, which allows VS 2008 to compile for .NET 2.0, 3.0, or 3.5 simply by changing a project property.<\/p>\n<p><a href=\"\/wp-content\/uploads\/WindowsLiveWriter\/MultitargetinginVisualStudio2008_ED3D\/ApplicationDesignerWindowPaneControl_4.png\"><img loading=\"lazy\" decoding=\"async\" style=\"border-top-width: 0px; border-left-width: 0px; border-bottom-width: 0px; border-right-width: 0px\" height=\"426\" alt=\"ApplicationDesignerWindowPaneControl\" src=\"\/wp-content\/uploads\/WindowsLiveWriter\/MultitargetinginVisualStudio2008_ED3D\/ApplicationDesignerWindowPaneControl_thumb_1.png\" width=\"742\" border=\"0\"><\/a> <\/p>\n<p>You might be thinking, now I don&#8217;t have to keep Visual Studio 2005 and 2008 installed. I can just use Visual Studio 2008 for all my projects! Well, yes, but with one big proviso. Code targeting .NET 2.0 and written in VS2008 may only compile in VS2008! The reality is that multi-targeting changes Intellisense, the project templates, and the assemblies that you&#8217;re offered, but your code is still compiled using the C# 3.0 or VB9 compilers regardless of which .NET Framework version you target. Compiling a project targeting .NET 2.0 using VS2008 results in this output:<\/p>\n<p><font face=\"Consolas\" size=\"2\">&#8212;&#8212; Build started: Project: Multitargetting, Configuration: Debug Any CPU &#8212;&#8212;<br \/>C:\\Windows\\Microsoft.NET\\Framework\\v3.5\\Csc.exe \/noconfig \/nowarn:1701,1702 \/errorreport:prompt \/warn:4 \/define:DEBUG;TRACE \/reference:C:\\Windows\\Microsoft.NET\\Framework\\v2.0.50727\\System.Data.dll \/reference:C:\\Windows\\Microsoft.NET\\Framework\\v2.0.50727\\System.dll \/reference:C:\\Windows\\Microsoft.NET\\Framework\\v2.0.50727\\System.Xml.dll \/debug+ \/debug:full \/filealign:512 \/optimize- \/out:obj\\Debug\\Multitargetting.exe \/target:exe Program.cs Properties\\AssemblyInfo.cs <\/font><\/p>\n<p><font face=\"Consolas\" size=\"2\">Compile complete &#8212; 0 errors, 0 warnings<br \/>Multitargetting -&gt; c:\\dev\\Examples\\Multitargetting\\Multitargetting\\bin\\Debug\\Multitargetting.exe<br \/>========== Build: 1 succeeded or up-to-date, 0 failed, 0 skipped ==========<\/font><\/p>\n<p>Note the path to csc.exe &#8211; C:\\Windows\\Microsoft.NET\\Framework\\v3.5. We&#8217;re using the C# 3.0 compiler that ships with .NET 3.5. (Don&#8217;t get me started about the renaming of WinFX to .NET 3.0 again. My friends at Microsoft already know how I feel about that one.) Generally this doesn&#8217;t matter because .NET 3.0 and .NET 3.5 are additive libraries to .NET 2.0. .NET 2.0, 3.0, and 3.5 all run on the CLR that shipped with .NET 2.0. (I originally read about this in Dustin Campbell&#8217;s <a href=\"http:\/\/diditwith.net\/2007\/11\/23\/C25.aspx\">C#2.5 post<\/a>.)<\/p>\n<p>So how do we get all the crazy goodness of lambda expressions, anonymous types, LINQ, extension methods, and more? In .NET 3.0, WCF, WPF, WF, and CardSpace were all just additive libraries on top of .NET 2.0. In .NET 3.5, the new features can be divided into two categories &#8211; additive libraries and compiler enhancements.<\/p>\n<table width=\"430\" border=\"0\">\n<tbody>\n<tr>\n<td width=\"255\"><strong><u>Feature<\/u><\/strong><\/td>\n<td align=\"middle\" width=\"80\"><strong><u>Library<\/u><\/strong><\/td>\n<td align=\"middle\" width=\"93\"><strong><u>Compiler<\/u><\/strong><\/td>\n<\/tr>\n<tr>\n<td width=\"254\">implicitly-typed locals (var)<\/td>\n<td align=\"middle\" width=\"81\">&nbsp;<\/td>\n<td align=\"middle\" width=\"94\">X<\/td>\n<\/tr>\n<tr>\n<td width=\"252\">lambda expressions<\/td>\n<td align=\"middle\" width=\"81\">&nbsp;<\/td>\n<td align=\"middle\" width=\"94\">X<\/td>\n<\/tr>\n<tr>\n<td width=\"252\">automatic properties<\/td>\n<td align=\"middle\" width=\"82\">&nbsp;<\/td>\n<td align=\"middle\" width=\"94\">X<\/td>\n<\/tr>\n<tr>\n<td width=\"251\">anonymous types<\/td>\n<td align=\"middle\" width=\"83\">&nbsp;<\/td>\n<td align=\"middle\" width=\"95\">X<\/td>\n<\/tr>\n<tr>\n<td width=\"249\">object and collection initializers<\/td>\n<td align=\"middle\" width=\"83\">&nbsp;<\/td>\n<td align=\"middle\" width=\"95\">X<\/td>\n<\/tr>\n<tr>\n<td width=\"249\">LINQ<\/td>\n<td align=\"middle\" width=\"84\">X<\/td>\n<td align=\"middle\" width=\"95\">X<\/td>\n<\/tr>\n<tr>\n<td width=\"248\">Expression Trees<\/td>\n<td align=\"middle\" width=\"84\">X<\/td>\n<td align=\"middle\" width=\"96\">X<\/td>\n<\/tr>\n<tr>\n<td width=\"247\">Extension Methods<\/td>\n<td align=\"middle\" width=\"85\">X*<\/td>\n<td align=\"middle\" width=\"97\">X<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>* See below<\/p>\n<p>Any feature not requiring library support is just syntactic sugar provided by our compilers. If you look under the covers using <a href=\"http:\/\/www.aisto.com\/roeder\/dotnet\/\">Lutz Roeder&#8217;s Reflector<\/a>, you&#8217;ll see that the compilers are generating the same old CLR 2.0-compatible MSIL as they always were.<\/p>\n<h3>Implicitly-Typed Locals<\/h3>\n<p>Let&#8217;s take a look at implicitly-typed locals using the &#8220;var&#8221; keyword:<\/p>\n<div style=\"font-size: 11pt; background: white; color: black; font-family: consolas, lucida console, monospace\">\n<pre style=\"margin: 0px\"><span style=\"color: blue\">var<\/span> foo = <span style=\"color: #a31515\">\"Hello, World!\"<\/span>;<\/pre>\n<pre style=\"margin: 0px\">&nbsp;<\/pre>\n<\/div>\n<div>Reflector says! (Harkening back to Family Feud and Richard Dawson.)<\/div>\n<div>&nbsp;<\/div>\n<div style=\"font-size: 11pt; background: white; color: black; font-family: consolas, lucida console, monospace\">\n<pre style=\"margin: 0px\"><span style=\"color: blue\">string<\/span> foo = <span style=\"color: #a31515\">\"Hello, World!\"<\/span>;<\/pre>\n<pre style=\"margin: 0px\">&nbsp;<\/pre>\n<\/div>\n<div>The compiler was able to infer the type of &#8220;foo&#8221; based on its usage. No magic MSIL instruction to infer type. It&#8217;s all in the compilers.<\/div>\n<h3>Lambdas<\/h3>\n<div>Let&#8217;s take a look at our new swanky lambda expressions:<\/div>\n<div>&nbsp;<\/div>\n<div style=\"font-size: 11pt; background: white; color: black; font-family: consolas, lucida console, monospace\">\n<pre style=\"margin: 0px\"><span style=\"color: #2b91af\">Action<\/span>&lt;<span style=\"color: blue\">string<\/span>&gt; display = msg =&gt; <span style=\"color: #2b91af\">Console<\/span>.WriteLine(msg);<\/pre>\n<\/div>\n<div>&nbsp;<\/div>\n<div>Reflector says!<\/div>\n<div>&nbsp;<\/div>\n<div style=\"font-size: 11pt; background: white; color: black; font-family: consolas, lucida console, monospace\">\n<pre style=\"margin: 0px\"><span style=\"color: #2b91af\">Action<\/span>&lt;<span style=\"color: blue\">string<\/span>&gt; display = <span style=\"color: blue\">delegate<\/span>(<span style=\"color: blue\">string<\/span> msg) { <span style=\"color: #2b91af\">Console<\/span>.WriteLine(msg); }<\/pre>\n<\/div>\n<div>&nbsp;<\/div>\n<div>Once again, it&#8217;s just compiler magic turning the terse lambda expression (that funky &#8220;params =&gt; body&#8221; syntax) into the anonymous delegate syntax that we&#8217;ve known and loved since .NET 2.0. (To be honest, that&#8217;s not quite what Reflector says. The C# compiler actually caches the anonymous delegate in a static field for performance reasons, but the code above is close enough for purposes of this discussion.)<\/div>\n<h3>Automatic Properties<\/h3>\n<p>What about automatic properties?<\/p>\n<div style=\"font-size: 11pt; background: white; color: black; font-family: consolas, lucida console, monospace\">\n<pre style=\"margin: 0px\"><span style=\"color: blue\">public<\/span> <span style=\"color: blue\">string<\/span> Hello { <span style=\"color: blue\">get<\/span>; <span style=\"color: blue\">set<\/span>; }<\/pre>\n<\/div>\n<p>Reflector says!<\/p>\n<pre>[CompilerGenerated]\nprivate string <b>&lt;Hello&gt;k__BackingField<\/b>;<\/pre>\n<pre>[CompilerGenerated]\npublic string <b>get_Hello<\/b>()\n{\n    return this.&lt;Hello&gt;k__BackingField;\n}<\/pre>\n<pre>[CompilerGenerated]\npublic void <b>set_Hello<\/b>(string value)\n{\n    this.&lt;Hello&gt;k__BackingField = <a>value<\/a>;\n}<\/pre>\n<div>Once again, more compiler magic.<\/div>\n<h3>Anonymous Types<\/h3>\n<div style=\"font-size: 11pt; background: white; color: black; font-family: consolas, lucida console, monospace\">\n<pre style=\"margin: 0px\"><span style=\"color: blue\">var<\/span> position = <span style=\"color: blue\">new<\/span> { Lat=42, Long=42 };<\/pre>\n<\/div>\n<p>Reflector says!<\/p>\n<pre>[CompilerGenerated, DebuggerDisplay(@\"\\{ Lat = {Lat}, Long = {Long} }\", Type=\"&lt;Anonymous Type&gt;\")]\ninternal sealed class &lt;&gt;f__AnonymousType0&lt;&lt;Lat&gt;j__TPar, &lt;Long&gt;j__TPar&gt; {\n  \/\/ Compiler generated goo omitted for clarity\n}\n<\/pre>\n<p>Compiler magic.<\/p>\n<h3>Object\/Collection Initializers<\/h3>\n<p>Object and collection initializers allow us to create and initialize objects\/collections in a single line. They only require that the object have a parameterless constructor.<\/p>\n<div style=\"font-size: 11pt; background: white; color: black; font-family: consolas, lucida console, monospace\">\n<pre style=\"margin: 0px\"><span style=\"color: #2b91af\">Program<\/span> program = <span style=\"color: blue\">new<\/span> <span style=\"color: #2b91af\">Program<\/span> { Hello=<span style=\"color: #a31515\">\"World\"<\/span> };<\/pre>\n<\/div>\n<div>&nbsp;<\/div>\n<div>Reflector says!<\/div>\n<pre>Program &lt;&gt;g__initLocal0 = new Program();\n&lt;&gt;g__initLocal0.Hello = \"World\";\nProgram program = &lt;&gt;g__initLocal0;\n<\/pre>\n<div>&nbsp;<\/div>\n<div>The C# 3.0 compiler is changing our object initializer into a plain old object instantiation via the parameterless constructor followed by a bunch of property sets. Nothing else to see here. Move it along&#8230;<\/div>\n<h3>LINQ, Expression Trees, and Extension Methods<\/h3>\n<p>Each of these features requires library support from System.Core, a new assembly that ships with .NET 3.5. Without System.Core installed in the GAC, your code isn&#8217;t going to run. So you can&#8217;t use these features without .NET 3.5 installed on the client.<\/p>\n<p>The one exception is extension methods. If you try to compile an extension method while targeting .NET 2.0, you will receive the following compile error:<\/p>\n<p>Cannot define a new extension method because the compiler required type &#8216;System.Runtime.CompilerServices.ExtensionAttribute&#8217; cannot be found. Are you missing a reference to System.Core.dll?<\/p>\n<p>As noted by Jared Parsons <a href=\"http:\/\/blogs.msdn.com\/jaredpar\/archive\/2007\/11\/16\/extension-methods-without-3-5-framework.aspx\">here<\/a>, you can simply define the attribute yourself:<\/p>\n<div style=\"font-size: 11pt; background: white; color: black; font-family: consolas, lucida console, monospace\">\n<pre style=\"margin: 0px\"><span style=\"color: blue\">namespace<\/span> System.Runtime.CompilerServices {<\/pre>\n<pre style=\"margin: 0px\">&nbsp;&nbsp;&nbsp; [<span style=\"color: #2b91af\">AttributeUsage<\/span>(<span style=\"color: #2b91af\">AttributeTargets<\/span>.Method)]<\/pre>\n<pre style=\"margin: 0px\">&nbsp;&nbsp;&nbsp; <span style=\"color: blue\">public<\/span> <span style=\"color: blue\">class<\/span> <span style=\"color: #2b91af\">ExtensionAttribute<\/span> : <span style=\"color: #2b91af\">Attribute<\/span> {<\/pre>\n<pre style=\"margin: 0px\">&nbsp;&nbsp;&nbsp; }<\/pre>\n<pre style=\"margin: 0px\">}<\/pre>\n<\/div>\n<p>Extension methods now compile while targeting .NET 2.0.<\/p>\n<p>N.B. If you target .NET 3.5 as well as .NET 2.0 with this code, you&#8217;ll end up with a duplicate definition warning under .NET 3.5 as noted by Dustin Campbell <a href=\"http:\/\/diditwith.net\/2007\/11\/23\/C25.aspx\">here<\/a>. If you&#8217;re really going to use this trick, you should probably wrap the class in some conditional directives that omit the definition when compiled under .NET 3.5.<\/p>\n<h3>Multi-targeting Proviso<\/h3>\n<p>What about that proviso I mentioned at the beginning of this post? If everyone on your project is using VS 2008 and targeting .NET 2.0, then all is good. You can use all the new syntactic sugary goodness that the C# 3.0 compiler (and VB9 compiler &#8211; if you swing that way) provides for you. If some team members are still using VS 2005, you need to be careful to not introduce C# 3.0 language constructs as VS2008 will not provide feedback that you are using them even if you target .NET 2.0. The new constructs are sufficiently different enough that it&#8217;s unlikely that you&#8217;ll mistakenly use a lambda expression or automatic property, but it&#8217;s something to keep in mind. Besides your CruiseControl.NET server is using a NAnt script that compiles with the C# 2.0 compiler to keep everyone honest, right? If not, this is yet another reason you should set up a CI server for your project today&#8230;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>A great new feature of Visual Studio 2008 is multi-targeting, which allows VS 2008 to compile for .NET 2.0, 3.0, or 3.5 simply by changing a project property. You might be thinking, now I don&#8217;t have to keep Visual Studio 2005 and 2008 installed. I can just use Visual Studio 2008 for all my projects! [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2],"tags":[],"class_list":["post-103","post","type-post","status-publish","format-standard","hentry","category-dotnetgeneral"],"_links":{"self":[{"href":"https:\/\/www.jameskovacs.com\/index.php\/wp-json\/wp\/v2\/posts\/103","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.jameskovacs.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.jameskovacs.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.jameskovacs.com\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.jameskovacs.com\/index.php\/wp-json\/wp\/v2\/comments?post=103"}],"version-history":[{"count":0,"href":"https:\/\/www.jameskovacs.com\/index.php\/wp-json\/wp\/v2\/posts\/103\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.jameskovacs.com\/index.php\/wp-json\/wp\/v2\/media?parent=103"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.jameskovacs.com\/index.php\/wp-json\/wp\/v2\/categories?post=103"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.jameskovacs.com\/index.php\/wp-json\/wp\/v2\/tags?post=103"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}