Có một vấn đề quan trọng và tế nhị mà không ai trong số họ giải quyết trực tiếp. Có hai cách để xem xét kiểu trong C #: kiểu tĩnh và kiểu thời gian chạy .
Loại tĩnh là loại biến trong mã nguồn của bạn. Do đó, nó là một khái niệm thời gian biên dịch. Đây là loại mà bạn thấy trong chú giải công cụ khi di chuột qua một biến hoặc thuộc tính trong môi trường phát triển của mình.
Bạn có thể lấy kiểu tĩnh bằng cách viết phương thức chung của trình trợ giúp để cho phép suy luận kiểu xử lý nó cho bạn:
Type GetStaticType<T>(T x) { return typeof(T); }
Kiểu thời gian chạy là kiểu của một đối tượng trong bộ nhớ. Do đó, nó là một khái niệm thời gian chạy. Đây là kiểu được trả về bởi GetType()phương thức.
Kiểu thời gian chạy của một đối tượng thường khác với kiểu tĩnh của biến, thuộc tính hoặc phương thức giữ hoặc trả về nó. Ví dụ: bạn có thể có mã như sau:
object o = "Some string";
Kiểu tĩnh của biến là object, nhưng tại thời điểm chạy, kiểu tham chiếu của biến là string. Do đó, dòng tiếp theo sẽ in "System.String" vào bảng điều khiển:
Console.WriteLine(o.GetType()); // prints System.String
Tuy nhiên, nếu bạn di chuột qua biến otrong môi trường phát triển của mình, bạn sẽ thấy loại System.Object(hoặc objecttừ khóa tương đương ). Bạn cũng thấy như vậy bằng cách sử dụng chức năng trợ giúp của chúng tôi từ phía trên:
Console.WriteLine(GetStaticType(o)); // prints System.Object
Đối với các biến giá trị gia loại, chẳng hạn như int, double, System.Guid, bạn biết rằng loại thời gian chạy sẽ luôn luôn giống như các loại tĩnh, bởi vì các loại giá trị không thể phục vụ như là lớp cơ sở cho loại hình khác; loại giá trị được đảm bảo là loại có nguồn gốc nhiều nhất trong chuỗi kế thừa của nó. Điều này cũng đúng với các kiểu tham chiếu được niêm phong: nếu kiểu tĩnh là kiểu tham chiếu được niêm phong, giá trị thời gian chạy phải là một phiên bản của kiểu đó hoặc null.
Ngược lại, nếu kiểu tĩnh của biến là kiểu trừu tượng thì được đảm bảo rằng kiểu tĩnh và kiểu thời gian chạy sẽ khác nhau.
Để minh họa điều đó trong mã:
// int is a value type
int i = 0;
// Prints True for any value of i
Console.WriteLine(i.GetType() == typeof(int));
// string is a sealed reference type
string s = "Foo";
// Prints True for any value of s
Console.WriteLine(s == null || s.GetType() == typeof(string));
// object is an unsealed reference type
object o = new FileInfo("C:\\f.txt");
// Prints False, but could be true for some values of o
Console.WriteLine(o == null || o.GetType() == typeof(object));
// FileSystemInfo is an abstract type
FileSystemInfo fsi = new DirectoryInfo("C:\\");
// Prints False for all non-null values of fsi
Console.WriteLine(fsi == null || fsi.GetType() == typeof(FileSystemInfo));
int