Reifikasi berarti secara umum (di luar ilmu komputer) "untuk membuat sesuatu yang nyata".
Dalam pemrograman, sesuatu dibenarkan jika kita dapat mengakses informasi dalam bahasa itu sendiri.
Untuk dua contoh yang sepenuhnya tidak berhubungan dengan generik tentang sesuatu yang C # lakukan dan tidak miliki terverifikasi, mari kita ambil metode dan akses memori.
Bahasa OO umumnya memiliki metode , (dan banyak yang tidak memiliki fungsi yang serupa meskipun tidak terikat ke kelas). Karena itu, Anda dapat menentukan metode dalam bahasa tersebut, menyebutnya, mungkin menimpanya, dan sebagainya. Tidak semua bahasa tersebut memungkinkan Anda menangani metode itu sendiri sebagai data untuk suatu program. C # (dan benar-benar, .NET, bukan C #) memungkinkan Anda menggunakan MethodInfo
objek yang mewakili metode, jadi dalam metode C # diverifikasi. Metode dalam C # adalah "objek kelas satu".
Semua bahasa praktis memiliki beberapa cara untuk mengakses memori komputer. Dalam bahasa tingkat rendah seperti C, kita bisa berurusan langsung dengan pemetaan antara alamat numerik yang digunakan oleh komputer, jadi suka int* ptr = (int*) 0xA000000; *ptr = 42;
itu masuk akal (selama kita punya alasan yang bagus untuk mencurigai bahwa mengakses alamat memori 0xA000000
dengan cara ini tidak akan menang ' t meledakkan sesuatu). Dalam C # ini tidak masuk akal (kita bisa memaksakannya dalam. NET, tetapi dengan manajemen memori .NET memindahkan hal-hal di sekitar itu tidak mungkin berguna). C # tidak memiliki alamat memori terverifikasi.
Jadi, sebagaimana ditolak berarti "menjadi nyata", "jenis yang ditegaskan" adalah jenis yang dapat kita "bicarakan" dalam bahasa yang dimaksud.
Dalam generik ini berarti dua hal.
Salah satunya adalah bahwa List<string>
adalah jenis seperti string
atau int
yang. Kita dapat membandingkan jenis itu, mendapatkan namanya, dan menanyakannya:
Console.WriteLine(typeof(List<string>).FullName); // System.Collections.Generic.List`1[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]
Console.WriteLine(typeof(List<string>) == (42).GetType()); // False
Console.WriteLine(typeof(List<string>) == Enumerable.Range(0, 1).Select(i => i.ToString()).ToList().GetType()); // True
Console.WriteLine(typeof(List<string>).GenericTypeArguments[0] == typeof(string)); // True
Konsekuensi dari hal ini adalah bahwa kita dapat "berbicara tentang" tipe parameter metode generik (atau metode kelas generik) dalam metode itu sendiri:
public static void DescribeType<T>(T element)
{
Console.WriteLine(typeof(T).FullName);
}
public static void Main()
{
DescribeType(42); // System.Int32
DescribeType(42L); // System.Int64
DescribeType(DateTime.UtcNow); // System.DateTime
}
Sebagai aturan, melakukan ini terlalu "bau", tetapi memiliki banyak kasus yang bermanfaat. Sebagai contoh, lihat:
public static TSource Min<TSource>(this IEnumerable<TSource> source)
{
if (source == null) throw Error.ArgumentNull("source");
Comparer<TSource> comparer = Comparer<TSource>.Default;
TSource value = default(TSource);
if (value == null)
{
using (IEnumerator<TSource> e = source.GetEnumerator())
{
do
{
if (!e.MoveNext()) return value;
value = e.Current;
} while (value == null);
while (e.MoveNext())
{
TSource x = e.Current;
if (x != null && comparer.Compare(x, value) < 0) value = x;
}
}
}
else
{
using (IEnumerator<TSource> e = source.GetEnumerator())
{
if (!e.MoveNext()) throw Error.NoElements();
value = e.Current;
while (e.MoveNext())
{
TSource x = e.Current;
if (comparer.Compare(x, value) < 0) value = x;
}
}
}
return value;
}
Ini tidak melakukan banyak perbandingan antara jenis TSource
dan berbagai jenis untuk perilaku yang berbeda (umumnya merupakan tanda bahwa Anda seharusnya tidak menggunakan obat generik sama sekali), tetapi memang memecah antara jalur kode untuk jenis yang dapat null
(harus kembali null
jika tidak ada elemen yang ditemukan, dan tidak boleh membuat perbandingan untuk menemukan minimum jika salah satu elemen dibandingkan adalah null
) dan jalur kode untuk tipe yang tidak dapat null
(harus dibuang jika tidak ada elemen yang ditemukan, dan tidak perlu khawatir tentang kemungkinan null
elemen ).
Karena TSource
"nyata" dalam metode ini, perbandingan ini dapat dibuat baik pada saat runtime atau waktu jitting (umumnya waktu jitting, tentu saja kasus di atas akan melakukannya pada waktu jitting dan tidak menghasilkan kode mesin untuk jalur yang tidak diambil) dan kami memiliki pisahkan versi "nyata" dari metode untuk setiap kasus. (Meskipun sebagai optimasi, kode mesin dibagikan untuk metode yang berbeda untuk parameter tipe tipe referensi yang berbeda, karena dapat tanpa mempengaruhi ini, dan karenanya kita dapat mengurangi jumlah kode mesin yang dipasangkan).
(Tidak umum untuk berbicara tentang reifikasi tipe generik dalam C # kecuali jika Anda juga berurusan dengan Java, karena dalam C # kami hanya menerima reifikasi ini; semua tipe diverifikasi. Di Jawa, tipe non-generik disebut sebagai reified karena itu adalah perbedaan antara mereka dan tipe generik).