Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does the C# compiler insert an explicit interface implementation?

I ran into a strange C# edge case and am looking for a good work-around.

There is a class that I do not control that looks like this:

namespace OtherCompany {     public class ClassIDoNotControl     {         public void SomeMethod(string argument)         {             Console.WriteLine((new StackFrame(1).GetMethod().Name));         }     } } 

I'd like to inherit from this class in a class I do control. Additionally, I'd like to specify an interface on it:

interface IInterfaceIDoControl {     void SomeMethod(string argument); }  class ClassIDoControl : OtherCompany.ClassIDoNotControl, IInterfaceIDoControl { } 

If all of these files are in the same assembly, everything works great:

namespace MyCompany {     class Program     {         static void Main(string[] args)         {             IInterfaceIDoControl i = new ClassIDoControl();             i.SomeMethod("Hello World!"); // Prints "Main"         }     }  } 

But, if I move "ClassIDoNotControl" into another assembly, I don't get what I expected. Instead, I see "MyCompany.IInterfaceIDoControl.SomeMethod" for the output implying an extra stack frame.

The reason is that under the covers, the C# compiler is changing "ClassIDoControl" to look like this:

class ClassIDoControl : OtherCompany.ClassIDoNotControl, IInterfaceIDoControl {     void IInterfaceIDoControl.SomeMethod(string argument)     {         base.SomeMethod(argument);     } } 

Is there a way to avoid this compiler-generated extra layer of indirection with explicitly implemented interfaces?

like image 596
Jeff Moser Avatar asked Sep 08 '10 13:09

Jeff Moser


People also ask

Why does the letter c exist?

Like the letter G, C emerged from the Phoenician letter gimel (centuries later, gimel became the third letter of the Hebrew alphabet). In ancient Rome, as the Latin alphabet was being adapted from the Greek and Etruscan alphabets, G and C became disambiguated by adding a bar to the bottom end of the C.

Does the letter c exist?

C, or c, is the third letter in the English and ISO basic Latin alphabets. Its name in English is cee (pronounced /ˈsiː/), plural cees.

Why does English have the letter c?

The letter c was applied by French orthographists in the 12th century to represent the sound ts in English, and this sound developed into the simpler sibilant s.

Why does c have the sound of S?

Here's the rule: When 'c' comes directly before the letters 'e', 'i' or 'y' we use the /s/ sound. in other cases we use a /k/ sound.


1 Answers

Short answer: The CLR requires that all methods that implement an interface method must be virtual (Ecma 335 Partition II Section 12.1).

Long answer:

  • If the method in the base class is already virtual, then nothing extra is needed: the interface method can be bound to it.

  • If the method in the base class is not virtual, but in the same assembly, the sneaky compiler actually makes it virtual and final. Reflector confirms this. (“final” is the CLR terminology for “sealed” in C#.)

  • If the method in the base class is not virtual and in another assembly, then obviously the compiler can’t do this because it can’t modify the already-compiled assembly. Therefore, the only option here is to insert a redirect method that implements the interface method. Like all methods that implement an interface method, it too is marked virtual and final.

So the answer to your last question, “Is there a way to avoid this?”, is unfortunately no.

like image 164
Timwi Avatar answered Sep 20 '22 20:09

Timwi