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コンストラクトは何をしますか?
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#コンパイラはhidebysig
を使用するため、Bar(string)
はBar()
を非表示にしないため、これは有効です。 「名前で隠す」セマンティクスを使用する場合、タイプDerived
の参照でBar()
を呼び出すことはできませんが、Baseにキャストしてそれを呼び出すことはできます。仕方。
編集:上記のコードをDLLにコンパイルし、それをildasmingし、Bar()
とBar(string)
のhidebysig
を削除し、もう一度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();
(コンパイルの問題はありません。)
THE SKEETの回答によると、これの理由はさらにJavaおよびC#により、クラスのクライアントが基本クラスのメソッドを含む同じ名前のメソッドを呼び出すことができるようになることです。C++ではnot:派生クラスで基本クラスのメソッドと同じ名前のメソッドが1つでも定義されている場合、同じ引数を取らなくても、クライアントは基本クラスメソッドを直接呼び出すことはできません。 CILでは、オーバーロードへの両方のアプローチをサポートします。
C++では、using
ディレクティブを使用して、基本クラスからオーバーロードの1つの名前付きセットを効果的にインポートして、それらがそのメソッド名の「オーバーロードセット」の一部になるようにすることができます。
Microsoft Docs によると
派生クラスのメンバーがC#の
new
修飾子またはVisual BasicのShadows
修飾子を使用して宣言されている場合、基本クラスの同じ名前のメンバーを非表示にすることができます。 C#は基本クラスのメンバーをシグネチャで非表示にします。つまり、基本クラスのメンバーに複数のオーバーロードがある場合、非表示になるのは、同じシグネチャを持つオーバーロードだけです。対照的に、Visual Basicはすべての基本クラスのオーバーロードを非表示にします。したがって、 IsHideBySig は、Visual Basicのfalse
修飾子で宣言されたメンバーではShadows
を返し、C#のtrue
修飾子で宣言されたメンバーではnew
を返します。