What is the purpose of hidebysig in a MSIL method?

Cil

Cil Problem Overview


Using ildasm and a C# program e.g.

static void Main(string[] args)
{
            
}

gives:

.method private hidebysig static void  Main(string[] args) cil managed
{
  .entrypoint
  // Code size       2 (0x2)
  .maxstack  8
  IL_0000:  nop
  IL_0001:  ret
} // end of method Program::Main

What does the hidebysig construct do?

Cil Solutions


Solution 1 - Cil

From ECMA 335, section 8.10.4 of partition 1:

> The CTS provides independent control > over both the names that are visible > from a base type (hiding) and the > sharing of layout slots in the derived > class (overriding). Hiding is > controlled by marking a member in the > derived class as either hide by name > or hide by name-and-signature. Hiding > is always performed based on the kind > of member, that is, derived field > names can hide base field names, but > not method names, property names, or > event names. If a derived member is > marked hide by name, then members of > the same kind in the base class with > the same name are not visible in the > derived class; if the member is marked > hide by name-and-signature then only a > member of the same kind with exactly > the same name and type (for fields) or > method signature (for methods) is > hidden from the derived class. > Implementation of the distinction > between these two forms of hiding is > provided entirely by source language > compilers and the reflection library; > it has no direct impact on the VES > itself.

(It's not immediately clear from that, but hidebysig means "hide by name-and-signature".)

Also in section 15.4.2.2 of partition 2:

> hidebysig is supplied for the use of > tools and is ignored by the VES. It > specifies that the declared method > hides all methods of the base class > types that have a matching method > signature; when omitted, the method > should hide all methods of the same > name, regardless of the signature.

As an example, suppose you have:

public class Base
{
    public void Bar()
    {
    }
}

public class Derived : Base
{
    public void Bar(string x)
    {
    }
}

...

Derived d = new Derived();
d.Bar();

That's valid, because Bar(string) doesn't hide Bar(), because the C# compiler uses hidebysig. If it used "hide by name" semantics, you wouldn't be able to call Bar() at all on a reference of type Derived, although you could still cast it to Base and call it that way.

EDIT: I've just tried this by compiling the above code to a DLL, ildasming it, removing hidebysig for Bar() and Bar(string), ilasming it again, then trying to call Bar() from other code:

Derived d = new Derived();
d.Bar();

Test.cs(6,9): error CS1501: No overload for method 'Bar' takes '0' arguments

However:

Base d = new Derived();
d.Bar();

(No compilation problems.)

Solution 2 - Cil

As per THE SKEET's answer, in addition the reason for this is that Java and C# allow the client of a class to call any methods with the same name, including those from base classes. Whereas C++ does not: if the derived class defines even a single method with the same name as a method in the base class, then the client cannot directly call the base class method, even if it doesn't take the same arguments. So the feature was included in CIL to support both approaches to overloading.

In C++ you can effectively import one named set of overloads from the base class with a using directive, so that they become part of the "overload set" for that method name.

Solution 3 - Cil

According to Microsoft Docs

> When a member in a derived class is declared with the C# new modifier > or the Visual Basic Shadows modifier, it can hide a member of the same > name in the base class. C# hides base class members by signature. That > is, if the base class member has multiple overloads, the only one that > is hidden is the one that has the identical signature. By contrast, > Visual Basic hides all the base class overloads. Thus, IsHideBySig > returns false on a member declared with the Visual Basic Shadows > modifier, and true on a member declared with the C# new modifier.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionrbraybView Question on Stackoverflow
Solution 1 - CilJon SkeetView Answer on Stackoverflow
Solution 2 - CilDaniel EarwickerView Answer on Stackoverflow
Solution 3 - CilAvesturaView Answer on Stackoverflow