locked
run-time generics exception RRS feed

  • Question

  • The following example compiles without errors, but causes an exception when executed. The exception message reads: 'tried to implicitly implement an interface method with weaker type parameter constraints'. I have two questions:
    Why does this exception occur when the code seems to be well formed?
    Why does this exception happen at run-time rather than compile time?

    Code Snippet

    namespace Test
    {
     interface IBase<T>
     {
      void Method<T1>() where T1: T;
     }

     class Base<T>: IBase<T>
     {
      public void Method<T1>() where T1: T
      {}
     }


     interface IDerived: IBase<int>
     {}

     class Derived: Base<int>, IDerived
     {}


     class Program
     {
      static void Main(string[] args)
      {
       IDerived s = new Derived();
      }
     }
    }

    Thanks,
    Tomas

    === Edited by tomc_bc @ 29 Mar 2007 9:32 PM UTC===
    I did some further investigation and here are the results:

    I rewrote the above code in managed C++ and surprisingly, the error did not occur. I disassembled the C# and C++ assemblies and found one relevant difference; below are snippets of the disassembled code:

    C#:
    .class private auto ansi beforefieldinit Test.Derived
           extends class Test.Base`1<int32>
           implements Test.IDerived,
                      class Test.IBase`1<int32>;
    C++:
    .class private auto ansi beforefieldinit Test.Derived
           extends class Test.Base`1<int32>;
           implements Test.IDerived

    I removed the 'class Test.IBase`1<int32>' declaration from the C# code and reassembled it. Lo and behold, this fixed the problem. Unless there is some reason why the C# code emitter is putting in the inherited interface implementation, I would venture to guess that this is a bug in the C# code emitter. Is there any way to make the C# code emitter work like the C++ code emitter?

    Your comments would be most appreciated.

     

    Thursday, March 29, 2007 6:25 PM

Answers

  • Tomas,

    you can avoid your error by implementing explicitly IBase in Base:

     

    Code Snippet

    class Base<T> : IBase<T> {

      void IBase<T>.Method<T1> () { }

    }

     

    HTH
    --mc

    Thursday, March 29, 2007 10:47 PM
  • Hi Thomas,

     

    I compiled and dissassembled your code with my C# 3.5 (Orcas) compiler and this is what I got

     

    .class private auto ansi beforefieldinit Test.Derived

    extends class Test.Base`1<int32>

    implements Test.IDerived,

    class Test.IBase`1<int32>

     

    It seems like this is a fixed bug Smile.

     

    Nice catch! and great explanation.

     

    Thanks,

     

    Marcelo.

     

    Friday, March 30, 2007 12:13 AM

All replies

  • Tomas,

    you can avoid your error by implementing explicitly IBase in Base:

     

    Code Snippet

    class Base<T> : IBase<T> {

      void IBase<T>.Method<T1> () { }

    }

     

    HTH
    --mc

    Thursday, March 29, 2007 10:47 PM
  • Hi Thomas,

     

    I compiled and dissassembled your code with my C# 3.5 (Orcas) compiler and this is what I got

     

    .class private auto ansi beforefieldinit Test.Derived

    extends class Test.Base`1<int32>

    implements Test.IDerived,

    class Test.IBase`1<int32>

     

    It seems like this is a fixed bug Smile.

     

    Nice catch! and great explanation.

     

    Thanks,

     

    Marcelo.

     

    Friday, March 30, 2007 12:13 AM