Reization có nghĩa là nói chung (bên ngoài khoa học máy tính) "để làm cho một cái gì đó thực sự".
Trong lập trình, cái gì đó đang reified nếu chúng tôi có thể truy cập thông tin về nó bằng ngôn ngữ riêng của mình.
Đối với hai ví dụ hoàn toàn không liên quan đến khái niệm về một thứ C # nào đó và không được thống nhất, hãy sử dụng các phương thức và truy cập bộ nhớ.
Các ngôn ngữ OO thường có các phương thức , (và nhiều ngôn ngữ không có các chức năng tương tự nhau mặc dù không bị ràng buộc với một lớp). Như vậy, bạn có thể định nghĩa một phương thức trong một ngôn ngữ như vậy, gọi nó, có thể ghi đè lên nó, v.v. Không phải tất cả các ngôn ngữ như vậy cho phép bạn thực sự đối phó với chính phương thức đó là dữ liệu cho một chương trình. C # (và thực sự, .NET chứ không phải C #) không cho phép bạn sử dụng các MethodInfo
đối tượng đại diện cho các phương thức, vì vậy trong các phương thức C # được thống nhất. Các phương thức trong C # là "đối tượng hạng nhất".
Tất cả các ngôn ngữ thực tế có một số phương tiện để truy cập vào bộ nhớ của máy tính. Trong một ngôn ngữ cấp thấp như C, chúng ta có thể xử lý trực tiếp ánh xạ giữa các địa chỉ số được sử dụng bởi máy tính, vì vậy lượt thích int* ptr = (int*) 0xA000000; *ptr = 42;
là hợp lý (miễn là chúng ta có lý do chính đáng để nghi ngờ rằng việc truy cập địa chỉ bộ nhớ 0xA000000
theo cách này sẽ thắng ' t thổi một cái gì đó lên). Trong C #, điều này không hợp lý (chúng ta có thể ép buộc nó bằng .NET, nhưng với việc quản lý bộ nhớ .NET, mọi thứ xung quanh sẽ không hữu dụng lắm). C # không có địa chỉ bộ nhớ hợp nhất.
Vì vậy, vì từ chối có nghĩa là "thực tế", "loại thống nhất" là loại mà chúng ta có thể "nói về" trong ngôn ngữ được đề cập.
Trong thuốc generic có nghĩa là hai điều.
Một trong số đó List<string>
là một loại giống như string
hoặc int
là. Chúng ta có thể so sánh loại đó, lấy tên của nó và hỏi về nó:
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
Hậu quả của điều này là chúng ta có thể "nói về" các kiểu tham số của phương thức chung (hoặc phương thức của lớp chung) trong chính phương thức:
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
}
Theo quy định, làm điều này quá nhiều là "có mùi", nhưng nó có nhiều trường hợp hữu ích. Ví dụ: nhìn vào:
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;
}
Điều này không có nhiều so sánh giữa loại TSource
và loại khác nhau cho các hành vi khác nhau (nói chung là một dấu hiệu bạn không nên sử dụng chung chung) nhưng nó phân chia giữa một đường dẫn mã cho các loại có thể null
(nên trả về null
nếu không tìm thấy phần tử nào và không được so sánh để tìm mức tối thiểu nếu một trong các phần tử được so sánh là null
) và đường dẫn mã cho các loại không thể null
(nên ném nếu không tìm thấy phần tử nào và không phải lo lắng về khả năng của null
các phần tử ).
Vì TSource
là "thực" trong phương thức, nên việc so sánh này có thể được thực hiện trong thời gian chạy hoặc thời gian jits (nói chung là thời gian jits, chắc chắn trường hợp trên sẽ làm như vậy tại thời điểm jits và không tạo mã máy cho đường dẫn không được thực hiện) và chúng tôi có một phiên bản "thực" riêng của phương pháp cho từng trường hợp. (Mặc dù là một tối ưu hóa, mã máy được chia sẻ cho các phương thức khác nhau cho các tham số loại tham chiếu khác nhau, bởi vì nó có thể không ảnh hưởng đến điều này và do đó chúng tôi có thể giảm số lượng mã máy bị giật).
(Đó là không phổ biến để nói về reification các loại chung trong C #, trừ khi bạn cũng đối phó với Java, bởi vì trong C # chúng ta chỉ mất reification này cho các cấp; tất cả các loại đang reified Trong Java, các loại phi generic được gọi là. Reified vì đó là một sự phân biệt giữa chúng và các loại chung chung).