Apa tujuan hidebysig dalam metode MSIL?

92

Menggunakan ildasm dan program C # misalnya

static void Main(string[] args)
{

}

memberikan:

.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

Apa yang dilakukan konstruksi hidebysig?

rbrayb.dll
sumber

Jawaban:

156

Dari ECMA 335 , bagian 8.10.4 dari partisi 1:

CTS menyediakan kontrol independen atas nama yang terlihat dari tipe dasar (bersembunyi) dan berbagi slot tata letak di kelas turunan (menimpa). Menyembunyikan dikontrol dengan menandai anggota di kelas turunan sebagai sembunyikan dengan nama atau sembunyikan dengan nama-dan-tanda tangan. Penyembunyian selalu dilakukan berdasarkan jenis anggota, yaitu, nama bidang turunan bisa menyembunyikan nama bidang dasar, tetapi tidak nama metode, nama properti, atau nama acara. Jika anggota turunan ditandai sembunyikan dengan nama, maka anggota sejenis di kelas dasar dengan nama yang sama tidak terlihat di kelas turunan; jika anggota ditandai sembunyikan dengan nama-dan-tanda tangan maka hanya anggota yang sama dengan nama dan jenis yang sama persis (untuk bidang) atau tanda tangan metode (untuk metode) disembunyikan dari kelas turunan. Implementasi perbedaan antara dua bentuk persembunyian ini sepenuhnya disediakan oleh penyusun bahasa sumber dan perpustakaan refleksi; itu tidak berdampak langsung pada VES itu sendiri.

(Tidak jelas dari itu, tetapi hidebysigberarti "sembunyikan dengan nama-dan-tanda tangan".)

Juga di bagian 15.4.2.2 dari partisi 2:

hidebysig disediakan untuk penggunaan alat dan diabaikan oleh VES. Ini menentukan bahwa metode yang dideklarasikan menyembunyikan semua metode dari tipe kelas dasar yang memiliki tanda tangan metode yang cocok; jika dihilangkan, metode tersebut harus menyembunyikan semua metode dengan nama yang sama, terlepas dari tanda tangannya.

Sebagai contoh, misalkan Anda memiliki:

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

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

...

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

Itu valid, karena Bar(string) tidak disembunyikan Bar(), karena kompilator C # menggunakan hidebysig. Jika menggunakan semantik "sembunyikan menurut nama", Anda tidak akan dapat memanggil Bar()sama sekali pada referensi jenis Derived, meskipun Anda masih bisa mentransmisikannya ke Basis dan menyebutnya seperti itu.

EDIT: Saya baru saja mencoba ini dengan mengompilasi kode di atas ke DLL, meng-ildasming, menghapus hidebysigfor Bar()dan Bar(string), ilasming lagi, lalu mencoba memanggil Bar()dari kode lain:

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

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

Namun:

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

(Tidak ada masalah kompilasi.)

Jon Skeet
sumber
4
Dalam ringkasan , itu perbedaan antara Shadowsdan Overloadsdi VB.NET.
Mark Hurd
15

Sesuai jawaban THE SKEET, sebagai tambahan alasannya adalah bahwa Java dan C # memungkinkan klien kelas untuk memanggil metode apa pun dengan nama yang sama, termasuk yang berasal dari kelas dasar. Sedangkan C ++ tidak: jika kelas turunan mendefinisikan bahkan satu metode dengan nama yang sama sebagai metode dalam kelas dasar, maka klien tidak dapat langsung memanggil metode kelas dasar, meskipun tidak mengambil argumen yang sama. Jadi, fitur tersebut dimasukkan dalam CIL untuk mendukung kedua pendekatan untuk kelebihan beban.

Di C ++ Anda dapat secara efektif mengimpor satu kumpulan kelebihan beban bernama dari kelas dasar dengan sebuah usingarahan, sehingga mereka menjadi bagian dari "kumpulan beban berlebih" untuk nama metode tersebut.

Daniel Earwicker
sumber
1

Menurut Microsoft Docs

Ketika anggota di kelas turunan dideklarasikan dengan newpengubah C # atau pengubah Visual Basic Shadows, itu bisa menyembunyikan anggota dengan nama yang sama di kelas dasar. C # menyembunyikan anggota kelas dasar dengan tanda tangan. Artinya, jika anggota kelas dasar memiliki beberapa kelebihan beban, satu-satunya yang disembunyikan adalah yang memiliki tanda tangan identik. Sebaliknya, Visual Basic menyembunyikan semua kelebihan kelas dasar. Jadi, IsHideBySig kembali falsepada anggota yang dideklarasikan dengan Shadows pengubah Visual Basic , dan truepada anggota yang dideklarasikan dengan newpengubah C # .

Avestura
sumber