Yeniden birleşme genellikle (bilgisayar biliminin dışında) "bir şeyi gerçek yapmak" anlamına gelir.
Programlamada, dilin kendisiyle ilgili bilgilere erişebiliyorsak , bir şey yeniden bilinir .
C # 'ın yaptığı ve bir araya getirilmemiş bir şey için tamamen jenerik olmayan iki örnek için, yöntemleri ve bellek erişimini ele alalım.
OO dilleri genellikle yöntemlere sahiptir (ve bir sınıfa bağlı olmasa da benzer işlevlere sahip olmayan birçok ). Bu nedenle, böyle bir dilde bir yöntem tanımlayabilir, onu çağırabilir, belki de geçersiz kılabilirsiniz, vb. Tüm bu diller aslında bir programa veri olarak yöntemin kendisini ele almanıza izin vermez. C # (ve gerçekten, C # yerine .NET) MethodInfo
yöntemleri temsil eden nesneleri kullanmanıza izin verir , bu nedenle C # yöntemleri yeniden birleştirilir. C # 'daki yöntemler "birinci sınıf nesneler" dir.
Tüm pratik dillerin bilgisayarın belleğine erişmek için bazı araçları vardır. C gibi düşük seviyeli bir dilde, bilgisayar tarafından kullanılan sayısal adresler arasındaki eşleme ile doğrudan başa çıkabiliriz, bu yüzden beğenileri int* ptr = (int*) 0xA000000; *ptr = 42;
makul (bellek adresine erişmenin 0xA000000
bu şekilde kazandığından şüphelenmek için iyi bir nedenimiz olduğu sürece) t bir şeyi havaya uçurmak). C # 'da bu makul değildir (hemen hemen .NET'te zorlayabiliriz, ancak .NET bellek yönetimi ile işleri hareket ettirmek yararlı olmayacaktır). C # 'ın bellek adresleri birleştirilmiş değil.
Dolayısıyla, refied anlamına gelen "gerçek yapmak" bir " birleşik tip" söz konusu dilde "hakkında konuşabileceğimiz" bir tiptir.
Jenerikte bu iki anlama gelir.
Bir olmasıdır List<string>
tıpkı türüdür string
veya int
bulunmaktadır. Bu türü karşılaştırabilir, adını alabilir ve sorgulayabiliriz:
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
Bunun bir sonucu olarak, yöntemin kendisinde bir genel yöntemin (veya bir genel sınıf yönteminin) parametrelerinin türleri hakkında "konuşabiliriz":
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
}
Kural olarak, bunu çok fazla yapmak "koklamak" dır, ancak birçok yararlı vakası vardır. Örneğin, şuna bakın:
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;
}
Bu türü arasındaki karşılaştırmalar çok yapmaz TSource
ve farklı davranışları için çeşitli türleri (eğer hiç jeneriği kullanmış gerektiğini genellikle bir işareti) ama olabilir türleri için bir kod yolu arasındaki bölünmüş yapar null
(dönmelidir null
eğer öğe bulunamadı ve karşılaştırılan öğelerden biri varsa minimum değeri bulmak için karşılaştırmalar yapmamalıdır null
) ve türler için kod yolu bulunamaz null
(hiçbir öğe bulunamazsa atılmalı ve null
öğelerin olasılığı hakkında endişelenmenize gerek yoktur) ).
TSource
Yöntem içinde "gerçek" olduğundan , bu karşılaştırma çalışma zamanında veya jitting zamanında yapılabilir (genellikle jitting zamanı, kesinlikle yukarıdaki durum jitting zamanında bunu yapar ve alınmayan yol için makine kodu üretmez) ve bir her durum için yöntemin ayrı "gerçek" sürümü. (Bir optimizasyon olmasına rağmen, makine kodu, farklı referans tipi tip parametreleri için farklı yöntemler için paylaşılır, çünkü bunu etkilemeden olabilir ve dolayısıyla verilen makine kodu miktarını azaltabiliriz).
(Java ile de ilgilenmediğiniz sürece, C # 'da genel türlerin yeniden yapılandırılması hakkında konuşmak yaygın değildir, çünkü C #' da sadece bu yeniden yapılandırmayı kabul ediyoruz; tüm türler yeniden birleştirilir. Java'da, genel olmayan türler reified olarak adlandırılır, çünkü bunlar ve genel türler arasındaki bir ayrımdır).