<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>Sam Ng's Blog : ModOpts</title><link>http://blogs.msdn.com/samng/archive/tags/ModOpts/default.aspx</link><description>Tags: ModOpts</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>Optional Modifiers and Overload Resolution</title><link>http://blogs.msdn.com/samng/archive/2008/03/05/optional-modifiers-and-overload-resolution.aspx</link><pubDate>Wed, 05 Mar 2008 09:12:24 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8046170</guid><dc:creator>samng</dc:creator><slash:comments>3</slash:comments><comments>http://blogs.msdn.com/samng/comments/8046170.aspx</comments><wfw:commentRss>http://blogs.msdn.com/samng/commentrss.aspx?PostID=8046170</wfw:commentRss><description>&lt;p&gt;Optional Modifiers (or &lt;em&gt;modopts&lt;/em&gt;) are CLR constructs that allow types to be annotated with optional information. This allows compiler writers to annotate their types with additional information that may not have a direct CLR representation. The managed C++ compiler for instance, uses modopts to represent const types. &lt;/p&gt;  &lt;p&gt;The C# compiler does not use modopts for anything - rather, we generally use attributes to augment code. For instance, the difference between &lt;em&gt;out &lt;/em&gt;and &lt;em&gt;ref &lt;/em&gt;is simply an attribute applied to the parameter - &lt;em&gt;out&lt;/em&gt; is just &lt;em&gt;ref&lt;/em&gt; with an attribute tacked onto it. Since the CLR does not consider attributes on parameters or return types as part of the method signature, methods that differ only in &lt;em&gt;out&lt;/em&gt; and &lt;em&gt;ref&lt;/em&gt; look the same. This is why the C# language does not allow you to have two overloads which differ only in their &lt;em&gt;out&lt;/em&gt; and &lt;em&gt;ref&lt;/em&gt;-ness.&lt;/p&gt;  &lt;p&gt;The same is not true of modopts, however. The CLR &lt;em&gt;does&lt;/em&gt; allow you to differentiate methods by their modopts. The following type is a fragment from a perfectly legal and verifiable assembly:&lt;/p&gt;  &lt;p&gt;&lt;font class="code"&gt;.class public auto ansi beforefieldinit Modopt      &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; extends [mscorlib]System.Object       &lt;br /&gt;{       &lt;br /&gt;&amp;#160; .method public hidebysig instance void       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Foo(int32 x) cil managed       &lt;br /&gt;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; ...       &lt;br /&gt;&amp;#160; } // end of method Modopt::Foo       &lt;br /&gt;&amp;#160; .method public hidebysig instance void       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; Foo(int32 modopt([mscorlib]IsConst) x) cil managed       &lt;br /&gt;&amp;#160; {       &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; ...       &lt;br /&gt;&amp;#160; } // end of method Modopt::Foo       &lt;br /&gt;&amp;#160; ...       &lt;br /&gt;} // end of class Modopt&lt;/font&gt;&lt;/p&gt;  &lt;p&gt;Regardless of the fact that none of the Microsoft .NET languages allow creation of such assemblies (ie C++ does not allow you to distinguish methods only by their &lt;em&gt;const&lt;/em&gt;-ness), the CLR allows this, and so compiler implementers that target the CLR must have some story when dealing with these assemblies.&lt;/p&gt;  &lt;p&gt;The C# compiler does not understand any modopts. When we encounter assemblies which contain modopts, we simply ignore them and import them as if they were regular members.&lt;/p&gt;  &lt;p&gt;When we import methods, we import each methods regardless of whether or not it has any modopts in it. We keep a note of the number of modopts in the method signature, but do not report any errors, even if there exist two imported methods which differ only in the modopts on their signature. &lt;/p&gt;  &lt;p&gt;At overload resolution time, we consider each method whose name matches that which we're resolving, and add it to the candidate set. We then filter the candidate set based on arguments and conversions, applying the algorithm described in section 7.4.2 of the &lt;a href="http://download.microsoft.com/download/3/8/8/388e7205-bc10-4226-b2a8-75351c669b09/CSharp%20Language%20Specification.doc" target="_blank"&gt;C# specification&lt;/a&gt;. At that point, if we're left with a candidate set in which all of the methods in the set are identical in signature with the exception of modopts, then we apply the rule that the method with the least number of modopts wins. If there is a tie between two or more methods with the minimal number of modopts, then the compiler reports an ambiguity error.&lt;/p&gt;  &lt;p&gt;This has several ramifications.&lt;/p&gt;  &lt;p&gt;Firstly, it allows methods with modopts not understood by the compiler to be called from the user's C# code. This has the arguable semantics of allowing the user to call a C++ function which expects a &lt;em&gt;const &lt;/em&gt;argument with one which is not &lt;em&gt;const&lt;/em&gt;, for instance. The philosophy of whether or not this is desirable can be argued, but by definition, these constructs are &lt;em&gt;optional&lt;/em&gt;, so according to the definition, this behavior is perfectly acceptable.&lt;/p&gt;  &lt;p&gt;Secondly, it allows importing assemblies which have the illegal-in-C# behavior of being overloaded only by modopts, and allows calling these methods from C# assemblies. Since the compiler doesn't understand the modopts, applying a simple deterministic heuristic seems as good behavior as one can expect.&lt;/p&gt;  &lt;p&gt;&amp;quot;Why can't we do better than applying a heuristic?&amp;quot; you ask. Well, we &lt;em&gt;could&lt;/em&gt; do better than that. We &lt;em&gt;could&lt;/em&gt; note which modopt type is used for each parameter, and despite not understanding it, use it as part of the better-ness algorithm in overload resolution. That would allow the compiler to do something like the following:&lt;/p&gt;  &lt;p&gt;In some assembly created from some other language:&lt;/p&gt;  &lt;blockquote&gt;   &lt;p&gt;&lt;font class="code"&gt;modopt(MyModopt) Foo();        &lt;br /&gt;void Bar(modopt(MyModopt) int x) { ... }         &lt;br /&gt;void Bar(int x) { ... }&lt;/font&gt;&lt;/p&gt; &lt;/blockquote&gt;  &lt;p&gt;And then in C#, for the call &lt;font class="code"&gt;Bar(Foo())&lt;/font&gt; we could determine that the modopt-ed Bar should be called because the return type of Foo has the matching modopt. However, as my colleague &lt;a href="http://blogs.msdn.com/ericlippert" target="_blank"&gt;Eric Lippert&lt;/a&gt; noted, &amp;quot;C# is not a glue language. If you want a glue-language, use VBA or something&amp;quot;. Nicely put. :)&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8046170" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/samng/archive/tags/CLR/default.aspx">CLR</category><category domain="http://blogs.msdn.com/samng/archive/tags/Optional+Modifiers/default.aspx">Optional Modifiers</category><category domain="http://blogs.msdn.com/samng/archive/tags/Overload+Resolution/default.aspx">Overload Resolution</category><category domain="http://blogs.msdn.com/samng/archive/tags/ModOpts/default.aspx">ModOpts</category></item></channel></rss>