MSILメソッドでのhidebysigの目的は何ですか?


92

ildasmとC#プログラムを使用する

static void Main(string[] args)
{

}

与える:

.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

hidebysigコンストラクトは何をしますか?

回答:


156

ECMA 335から、パーティション1のセクション8.10.4:

CTSは、基本タイプから見える名前(非表示)と派生クラスのレイアウトスロットの共有(上書き)の両方を独立して制御します。非表示は、派生クラスのメンバーを名前で非表示にするか、名前と署名で非表示にするかのいずれかとしてマークすることによって制御されます。非表示は常にメンバーの種類に基づいて実行されます。つまり、派生フィールド名はベースフィールド名を非表示にできますが、メソッド名、プロパティ名、イベント名は非表示にできません。派生メンバーが名前で非表示としてマークされている場合、同じ名前の基本クラスの同じ種類のメンバーは、派生クラスでは表示されません。メンバーが名前と署名によって非表示とマークされている場合、完全に同じ名前とタイプ(フィールドの場合)またはメソッドシグネチャ(メソッドの場合)を持つ同じ種類のメンバーのみが派生クラスから非表示になります。これら2つの形式の非表示の区別の実装は、完全にソース言語コンパイラとリフレクションライブラリによって提供されます。VES自体に直接的な影響はありません。

(それはすぐにはわかりませんが、hidebysig「名前と署名で非表示にする」という意味です。)

また、パーティション2のセクション15.4.2.2にも:

hidebysigはツールの使用のために提供されており、VESによって無視されます。宣言されたメソッドが、一致するメソッドシグネチャを持つ基本クラス型のすべてのメソッドを隠すことを指定します。省略した場合、シグネチャに関係なく、メソッドは同じ名前のすべてのメソッドを非表示にする必要があります。

例として、次のように仮定します。

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

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

...

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

C#コンパイラはを使用するため、Bar(string) 非表示Bar()しないため、これ有効ですhidebysig。「名前による非表示」セマンティクスを使用する場合Bar()は、typeの参照を呼び出すことはできませんがDerived、Baseにキャストしてそのように呼び出すことはできます。

編集:上記のコードをDLLにコンパイルし、それをildasmingし、を削除hidebysigBar()Bar(string)再度ilasmingしてBar()から、他のコードから呼び出してみました:

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

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

しかしながら:

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

(コンパイルの問題はありません。)


4
まとめ、それが違いだShadowsOverloadsVB.NETインチ
Mark Hurd、2014

16

THE SKEETの回答によると、これの理由は、JavaとC#により、クラスのクライアントが、基本クラスのメソッドを含め、同じ名前のメソッドを呼び出すことができるためです。一方、C ++では、派生クラスで基本クラスのメソッドと同じ名前のメソッドが1つでも定義されている場合、クライアントは基本クラスメソッドを直接呼び出すことができません。そのため、この機能はCILに含まれており、過負荷に対する両方のアプローチをサポートしています。

C ++では、usingディレクティブを使用して基本クラスからオーバーロードの1つの名前付きセットを効果的にインポートして、それらがそのメソッド名の「オーバーロードセット」の一部になるようにすることができます。


1

Microsoft Docsによると

派生クラスのメンバーがC#new修飾子またはVisual Basic Shadows修飾子で宣言されている場合、基本クラスの同じ名前のメンバーを非表示にすることができます。C#は基本クラスのメンバーをシグネチャで非表示にします。つまり、基本クラスのメンバーに複数のオーバーロードがある場合、非表示になるのは、同じシグネチャを持つオーバーロードだけです。対照的に、Visual Basicはすべての基本クラスのオーバーロードを非表示にします。したがって、IsHideBySigfalse、Visual Basic Shadows 修飾子でtrue宣言されたメンバー、およびC#new修飾子で宣言されたメンバーに戻ります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.