2015-05-29 12 views
9

Nhìn vào đoạn code mẫu dưới đâyActivator.CreateInstance tạo ra giá trị của loại T thay vì Nullable <T>

var genericNullableType = typeof(Nullable<>); 
var nullableType = genericNullableType.MakeGenericType(typeof(bool)); 
var returnValue = Activator.CreateInstance(nullableType, (object)false); 

Đối với một số lý do biến returnValue sẽ loại bool và không bool?. Tại sao điều đó và làm thế nào nó có thể tránh được?

UPD: Đây là một ảnh chụp màn hình từ tôi VS enter image description here

+0

@petelids Tôi đang sử dụng VS 2013 Premium và .NET Framework 4.5 và cấu hình xây dựng là Gỡ lỗi. Bạn có sử dụng cùng một cấu hình không? – Demarsch

+1

Đây không phải là duy nhất cho 'Trình kích hoạt'. 'Console.WriteLine ((Nullable (sai) .GetType(). FullName));' cũng chỉ phát ra Boolean đơn giản. – vcsjones

+1

Không có cách nào để có được một ô không có giá trị. Thời gian chạy có xử lý đặc biệt cho boxing boxing và sẽ luôn luôn unwrap nó vào một giá trị đóng hộp của các loại cơ bản hoặc một tài liệu tham khảo null. Điều đó nói rằng nó nên được castable như là một bool? 'Vì vậy tôi không chắc chắn những gì bạn đang tìm kiếm. –

Trả lời

15

Trong trường hợp này bạn đang sử dụng sự quá tải của CreateInstance trả về object. Nullable<T>struct do đó được đại diện là object nó sẽ cần phải được đóng hộp. Tuy nhiên, Nullable<T> thực sự không thể được đóng hộp theo các quy tắc của CLR. Thay vào đó, giá trị cơ bản hoặc null được sử dụng. Đây là lý do tại sao bạn nhận được bool thô ở đây thay vì bool?.

Tài liệu: https://msdn.microsoft.com/en-us/library/ms228597.aspx

EDIT

Dường như có một số rắc rối xung quanh việc xác định loại của một giá trị là nullable hay không. Đặc biệt nó được chỉ ra rằng các bản in sau System.Boolean và không System.Nullable``1[System.Boolean]:

var x = (bool?)true; 
Console.WriteLine(x.GetType()); 

Mã này cũng được trở thành con mồi để boxing. Các cuộc gọi đến GetType có một hoạt động đấm bốc ngầm bởi vì nó là một lời gọi của một phương pháp ảo trên object, không phải là một phương pháp trên Nullable<T>:

IL_0009: ldloc.0 
IL_000a: box valuetype [mscorlib]System.Nullable`1<bool> 
IL_000f: call instance class [mscorlib]System.Type [mscorlib]System.Object::GetType() 
IL_0014: call void [mscorlib]System.Console::WriteLine(object) 

Cách an toàn nhất để in ra các loại thực tế của một giá trị var là làm theo ý lừa sau với generics:

static void PrintType<T>(T value) 
{ 
    Console.WriteLine(typeof(T)); 
} 

PrintType(x); // Prints System.Nullable`1[System.Boolean] 
+0

Ngay cả khi một bài đăng khác quá tải của CreateInstance đã được sử dụng, GetType sẽ vẫn nội bộ hộp bởi vì nó là không ảo, do đó bạn sẽ không bao giờ nhìn thấy một 'Nullable ' ra khỏi GetType, chính xác? –

+0

@mikez đúng. Lệnh gọi 'GetType()' tạo ra một mã lệnh '.box' il implicit ngầm định ngăn chặn nó loại bỏ kiểu nullable. Để có được loại in thực sự bạn cần sử dụng Generics. Sẽ chứng minh rằng chỉ trong một giây. – JaredPar

Các vấn đề liên quan