<?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 : Generics</title><link>http://blogs.msdn.com/samng/archive/tags/Generics/default.aspx</link><description>Tags: Generics</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>Generic Method Substitutions and Unification - Part two</title><link>http://blogs.msdn.com/samng/archive/2008/03/04/generic-method-substitutions-and-unification-part-two.aspx</link><pubDate>Tue, 04 Mar 2008 07:24:56 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:8018693</guid><dc:creator>samng</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/samng/comments/8018693.aspx</comments><wfw:commentRss>http://blogs.msdn.com/samng/commentrss.aspx?PostID=8018693</wfw:commentRss><description>&lt;p&gt;Last time we talked about generic method substitutions which resulted in types being declared with more than one method with identical constructed signatures. After thinking long and hard about this problem, we've come to a conclusion as to how to resolve this issue in the next release. &lt;/p&gt;  &lt;p&gt;First, lets recap what we know about the problem.&lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;We currently produce code which causes the CLR to throw TypeLoadExceptions at runtime. &lt;/li&gt;    &lt;li&gt;Code that falls into this scenario can be easily fixed by a simple rename &lt;/li&gt;    &lt;li&gt;It is a corner case - typical coding practices will not get you into this scenario &lt;/li&gt;    &lt;li&gt;The code written is not CLS-compliant &lt;/li&gt; &lt;/ol&gt;  &lt;p&gt;The following is a general set of categories that can result in this scenario occurring:&lt;/p&gt;  &lt;pre class="code"&gt;&lt;span style="color: green"&gt;// Same class
&lt;/span&gt;&lt;span style="color: blue"&gt;class &lt;/span&gt;&lt;span style="color: #2b91af"&gt;Base&lt;/span&gt;&amp;lt;T&amp;gt;
{
    &lt;span style="color: blue"&gt;void &lt;/span&gt;Foo(T t);
    &lt;span style="color: blue"&gt;void &lt;/span&gt;Foo(&lt;span style="color: blue"&gt;int &lt;/span&gt;t);
}
 
&lt;span style="color: blue"&gt;class &lt;/span&gt;&lt;span style="color: #2b91af"&gt;C &lt;/span&gt;: &lt;span style="color: #2b91af"&gt;Base&lt;/span&gt;&amp;lt;&lt;span style="color: blue"&gt;int&lt;/span&gt;&amp;gt; { }
 
&lt;span style="color: green"&gt;// Inherited from base class
&lt;/span&gt;&lt;span style="color: blue"&gt;class &lt;/span&gt;&lt;span style="color: #2b91af"&gt;A
&lt;/span&gt;{
    &lt;span style="color: blue"&gt;void &lt;/span&gt;Foo(&lt;span style="color: blue"&gt;int &lt;/span&gt;i) { }
}
 
&lt;span style="color: blue"&gt;class &lt;/span&gt;&lt;span style="color: #2b91af"&gt;B&lt;/span&gt;&amp;lt;T&amp;gt; : &lt;span style="color: #2b91af"&gt;A
&lt;/span&gt;{
    &lt;span style="color: blue"&gt;void &lt;/span&gt;Foo(T t) { }
}
 
&lt;span style="color: blue"&gt;class &lt;/span&gt;&lt;span style="color: #2b91af"&gt;C &lt;/span&gt;: &lt;span style="color: #2b91af"&gt;B&lt;/span&gt;&amp;lt;&lt;span style="color: blue"&gt;int&lt;/span&gt;&amp;gt; { }
 
&lt;span style="color: green"&gt;// Outer class
&lt;/span&gt;&lt;span style="color: blue"&gt;class &lt;/span&gt;&lt;span style="color: #2b91af"&gt;A&lt;/span&gt;&amp;lt;T&amp;gt;
{
    &lt;span style="color: blue"&gt;private void &lt;/span&gt;Foo(T t) { }
    &lt;span style="color: blue"&gt;private void &lt;/span&gt;Foo(&lt;span style="color: blue"&gt;int &lt;/span&gt;i) { }
 
    &lt;span style="color: blue"&gt;class &lt;/span&gt;&lt;span style="color: #2b91af"&gt;C &lt;/span&gt;: &lt;span style="color: #2b91af"&gt;A&lt;/span&gt;&amp;lt;&lt;span style="color: blue"&gt;int&lt;/span&gt;&amp;gt; { }
}
 
&lt;span style="color: green"&gt;// Outer class and its base class
&lt;/span&gt;&lt;span style="color: blue"&gt;class &lt;/span&gt;&lt;span style="color: #2b91af"&gt;A&lt;/span&gt;&amp;lt;T&amp;gt;
{
    &lt;span style="color: blue"&gt;public void &lt;/span&gt;Foo(T t) { }
}
 
&lt;span style="color: blue"&gt;class &lt;/span&gt;&lt;span style="color: #2b91af"&gt;B&lt;/span&gt;&amp;lt;T&amp;gt; : &lt;span style="color: #2b91af"&gt;A&lt;/span&gt;&amp;lt;T&amp;gt;
{
    &lt;span style="color: blue"&gt;private void &lt;/span&gt;Foo(&lt;span style="color: blue"&gt;int &lt;/span&gt;i) { }
    &lt;span style="color: blue"&gt;class &lt;/span&gt;&lt;span style="color: #2b91af"&gt;C &lt;/span&gt;: &lt;span style="color: #2b91af"&gt;B&lt;/span&gt;&amp;lt;&lt;span style="color: blue"&gt;int&lt;/span&gt;&amp;gt; { }
}&lt;/pre&gt;

&lt;p&gt;Given the above points, we've decided to take the following action:&lt;/p&gt;

&lt;ol&gt;
  &lt;li&gt;If the user specifies that the type is CLS-compliant (via the CLSCompliantAttribute attribute), the compiler will produce a warning indicating that the constructed type is not CLS-compliant &lt;/li&gt;

  &lt;li&gt;If the user does not specify CLS compliance, or specifies that the type is &lt;em&gt;not&lt;/em&gt; CLS-compliant, then we will keep our current behavior, allow the type to be emitted, and produce an assembly that will throw a runtime exception. &lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;This behavior will make it into the next release of the compiler. Until then, don't write code like this if you want it to work! Stay tuned for my investigations on the C# Compiler and modopts!&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=8018693" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/samng/archive/tags/Generics/default.aspx">Generics</category><category domain="http://blogs.msdn.com/samng/archive/tags/CLR/default.aspx">CLR</category><category domain="http://blogs.msdn.com/samng/archive/tags/CLS+compliance/default.aspx">CLS compliance</category></item><item><title>generic method substitutions and unification</title><link>http://blogs.msdn.com/samng/archive/2008/02/13/generic-method-substitutions-and-unification.aspx</link><pubDate>Wed, 13 Feb 2008 20:17:03 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:7677853</guid><dc:creator>samng</dc:creator><slash:comments>6</slash:comments><comments>http://blogs.msdn.com/samng/comments/7677853.aspx</comments><wfw:commentRss>http://blogs.msdn.com/samng/commentrss.aspx?PostID=7677853</wfw:commentRss><description>&lt;p&gt;It's been a while since I've last written - my apologies. We've been hard at work figuring out what the next release of C# will look like, and I'm happy to say that I'm &lt;em&gt;very&lt;/em&gt; excited about what we're working on. Great minds are at work figuring out things like integration of C# with the DLR, dynamic late binding, and better debugging experiences as we speak. Don't worry, I'll be sure to report to you about what &lt;em&gt;they&lt;/em&gt; determine. :)&lt;/p&gt;  &lt;p&gt;I'm always fascinated by discovering subtle details in the language that baffle me. Today I came across such a case. Consider the following code:&lt;/p&gt;  &lt;pre class="code"&gt;&lt;span style="color: blue"&gt;using &lt;/span&gt;System;

&lt;span style="color: blue"&gt;abstract class &lt;/span&gt;A&amp;lt;T&amp;gt;
{
    &lt;span style="color: blue"&gt;public abstract void &lt;/span&gt;Foo(T x);
}

&lt;span style="color: blue"&gt;abstract class &lt;/span&gt;B&amp;lt;T, S&amp;gt; : A&amp;lt;T&amp;gt;
{
    &lt;span style="color: blue"&gt;public virtual void &lt;/span&gt;Foo(S x){}
}

&lt;span style="color: blue"&gt;abstract class &lt;/span&gt;C&amp;lt;T, S&amp;gt; : B&amp;lt;T, S&amp;gt;
{
    &lt;span style="color: blue"&gt;public abstract override void &lt;/span&gt;Foo(T x);
}

&lt;span style="color: blue"&gt;class &lt;/span&gt;D : C&amp;lt;&lt;span style="color: blue"&gt;int&lt;/span&gt;, &lt;span style="color: blue"&gt;int&lt;/span&gt;&amp;gt;
{
    &lt;span style="color: blue"&gt;public override void &lt;/span&gt;Foo(&lt;span style="color: blue"&gt;int &lt;/span&gt;x) {}

    &lt;span style="color: blue"&gt;static void &lt;/span&gt;Main()
    {
        &lt;span style="color: blue"&gt;new &lt;/span&gt;D().Foo(1);
    }
}&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;What happens here?&lt;/p&gt;

&lt;p&gt;Well, on the surface, this looks like it should be correct right? A's Foo and B's Foo are different, since they have different generic type parameters, and C clearly overrides A's Foo. But the weird part is D's Foo. Does it override A::Foo? Or B::Foo?&lt;/p&gt;

&lt;p&gt;Well, it turns out that the specification outlines that when we look up members to override, we look from our current parent up - that is, when we find a method in one base class, we use that, regardless of other matches in higher ancestral classes. So since C is D's direct base class, D::Foo overrides C::Foo, which overrides the abstract A::Foo.&lt;/p&gt;

&lt;p&gt;So we should be good here right? A::Foo has an implementation in D::Foo, and B::Foo has its own implementation as well. But we're not. We get a runtime type load exception, which complains that D has a method Foo with no body.&lt;/p&gt;

&lt;p&gt;Well that's odd! I thought we just said that everything has an implementation!&lt;/p&gt;

&lt;p&gt;So, being the inquisitive minded person that I am, (and of course, having a bug open to fix this issue), I went and poked around, and discovered that we could fix this problem by having the compiler emit the .override instruction, so that the CLR will know exactly which method we're overriding.&lt;/p&gt;

&lt;p&gt;Well neat, that fixes that problem. Or so I thought!&lt;/p&gt;

&lt;p&gt;Bug number two looks a little different, but very similar. &lt;/p&gt;

&lt;pre class="code"&gt;&lt;span style="color: blue"&gt;using &lt;/span&gt;System;

&lt;span style="color: blue"&gt;class &lt;/span&gt;&lt;span style="color: #2b91af"&gt;A&lt;/span&gt;&amp;lt;T&amp;gt;
{
    &lt;span style="color: blue"&gt;protected virtual void &lt;/span&gt;Foo(T x){}
}

&lt;span style="color: blue"&gt;class &lt;/span&gt;&lt;span style="color: #2b91af"&gt;B&lt;/span&gt;&amp;lt;T, S&amp;gt; : &lt;span style="color: #2b91af"&gt;A&lt;/span&gt;&amp;lt;T&amp;gt;
{
    &lt;span style="color: blue"&gt;public virtual void &lt;/span&gt;Foo(S x) {}
}

&lt;span style="color: blue"&gt;class &lt;/span&gt;&lt;span style="color: #2b91af"&gt;C&lt;/span&gt;&amp;lt;T, S&amp;gt; : &lt;span style="color: #2b91af"&gt;B&lt;/span&gt;&amp;lt;T, S&amp;gt;
{
    &lt;span style="color: blue"&gt;protected override void &lt;/span&gt;Foo(T x) { }
}

&lt;span style="color: blue"&gt;class &lt;/span&gt;&lt;span style="color: #2b91af"&gt;D &lt;/span&gt;: &lt;span style="color: #2b91af"&gt;C&lt;/span&gt;&amp;lt;&lt;span style="color: blue"&gt;int&lt;/span&gt;, &lt;span style="color: blue"&gt;int&lt;/span&gt;&amp;gt;
{
    &lt;span style="color: blue"&gt;protected override void &lt;/span&gt;Foo(&lt;span style="color: blue"&gt;int &lt;/span&gt;x) {}
    
    &lt;span style="color: blue"&gt;static void &lt;/span&gt;Main()
    {
        &lt;span style="color: blue"&gt;new &lt;/span&gt;&lt;span style="color: #2b91af"&gt;D&lt;/span&gt;();
    }
}&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;In this scenario, the compiler again allows us to compile the code without problems, and once again we get a runtime exception. This time, we get an exception saying that we're attempting to lower the access of B::Foo. Interesting. This looks like my first bug! So what do I do? I apply the fix to my first bug and see what happens.&lt;/p&gt;

&lt;p&gt;No luck. &lt;/p&gt;

&lt;p&gt;&amp;quot;But why not?&amp;quot;, you ask? Well, after more digging (and finding the right contacts on the CLR team to chat with), we discovered that the initial fix was wrong! It turns out that by specifying the .override command, we tell the CLR to override A::Foo, but the CLR also finds B::Foo and tells D:Foo to override that as well. &lt;/p&gt;

&lt;p&gt;At the end of it all, we discovered that the entire scenario is an error. Why? The CLI spec, chapter 11.9.9 &amp;quot;Inheritance and overriding&amp;quot; outlines:&lt;/p&gt;

&lt;p&gt;&lt;/p&gt;

&lt;h6&gt;Type definitions are invalid if, after substituting base class generic arguments, two methods result in the same name and signature (including return type). The following illustrates this point:&lt;/h6&gt;

&lt;h6&gt;[&lt;i&gt;Example:&lt;/i&gt;&lt;/h6&gt;

&lt;h6&gt;.class B`1&amp;lt;T&amp;gt;&lt;/h6&gt;

&lt;h6&gt;{ .method public virtual void V(!0 t) { &amp;#8230; }&lt;/h6&gt;

&lt;h6&gt;.method public virtual void V(string x) { &amp;#8230; }&lt;/h6&gt;

&lt;h6&gt;}&lt;/h6&gt;

&lt;h6&gt;.class D extends B`1&amp;lt;string&amp;gt; { } // Invalid&lt;/h6&gt;

&lt;h6&gt;Class D is invalid, because it will inherit from B&amp;lt;string&amp;gt; two methods with identical signatures:&lt;/h6&gt;

&lt;h6&gt;void V(string)&lt;/h6&gt;

&lt;p&gt;At the end of it all, we discovered that we have a disconnect between the CLR and the C# compiler here. We're currently working on determining what C# spec changes we'll need to make to clarify this case, and from there we'll put a fix together.&lt;/p&gt;

&lt;p&gt;So what did I learn today? Two things:&lt;/p&gt;

&lt;p&gt;1) Our customer that found this bug (I only know them as nikov) is great at finding an exploit, and then massaging it in all possible ways to find other problems (which I might add, is &lt;em&gt;phenomenal). &lt;/em&gt;&lt;/p&gt;

&lt;p&gt;2) People should just not code like this cause its confusing and doesn't work :)&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=7677853" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/samng/archive/tags/Generics/default.aspx">Generics</category><category domain="http://blogs.msdn.com/samng/archive/tags/CLR/default.aspx">CLR</category></item></channel></rss>