2011-01-22 46 views

Trả lời

14

Lưu ý rằng lĩnh vực đang ngầm khởi tạo null, vì vậy đây chỉ ảnh hưởng đến các biến. Trong tinh khiết C# bạn không thể truy vấn giá trị của trường chưa được khởi tạo (bạn cần "phân bổ xác định"), do đó, nó không phải là câu hỏi.

Bạn có thể làm điều này bằng cách lạm dụng IL mặc dù - bằng cách tuyên bố một tham số out, và sử dụng DynamicMethod để viết một phương pháp mà không gán nó (có giá trị trong IL, nhưng không phải trong C#). Và sau đó bạn thấy rằng bạn sẽ thấy null s.

Điều này lần lượt là do cờ IL (.locals init) cho biết "xóa ngăn xếp cho tôi trước khi nhập phương thức này" trên gọi mã (C#). Trình biên dịch C# luôn đặt cờ này. Nếu bạn lại lạm dụng IL để viết một phương thức không đặt cờ này, bạn có thể thấy rác. Có thể là mọi thứ. Nhưng thời điểm này, bạn xứng đáng với trường hợp ngoại lệ bạn nhận được :)

Dưới đây là một ví dụ về người đầu tiên (không phải là thứ hai, đó là phức tạp hơn):

delegate void AbuseMe(out object foo); 
static void Main() { 
    DynamicMethod dyn = new DynamicMethod("Foo", 
     typeof(void), new[] { typeof(object).MakeByRefType() }); 
    dyn.GetILGenerator().Emit(OpCodes.Ret); 
    AbuseMe method = (AbuseMe) dyn.CreateDelegate(typeof(AbuseMe)); 
    object obj; // this **never** gets assigned, by **any** code 
    method(out obj); 
    Console.WriteLine(obj == null); 
} 

Để làm rõ, mã DynamicMethod chỉ đơn giản là viết tương đương với mã này, không hợp pháp trong C#:

static void Foo(out object whatever) { } // note, whatever is not assigned 

này hoạt động vì như xa như CLR là có liên quanout không tồn tại - chỉ có ref . Vì vậy, đây không phải là không hợp lệ IL - nó chỉ là ngôn ngữ (C#) mà đặt ý nghĩa để out và yêu cầu rằng nó được gán một giá trị.

Vấn đề là Main() vẫn có cờ .locals init; nên đằng sau hậu trường obj được xóa thành null (tốt, toàn bộ không gian ngăn xếp chỉ đơn giản là bị xóa). Nếu tôi biên soạn từ IL mà không có lá cờ đó (và có một số mã khác tại chỗ để làm cho không gian ngăn xếp bẩn) Tôi có thể nhìn thấy rác. Bạn có thể xem thêm về .locals init trên Liran Chen's blog.

Tuy nhiên, để trả lời câu hỏi:

  • cho các lĩnh vực: lĩnh vực tài liệu tham khảo kiểu uninitialized là null - đảm bảo bởi spec
  • cho các biến: bạn không thể yêu cầu, nhưng như một thực hiện chi tiết (không được phụ thuộc vào): có, nó sẽ là nullmặc dù bạn không thể hỏi; p
+2

Ok, đó là khá freaky sh! T! :) – leppie

+0

@leppie Tôi muốn làm hài lòng, p –

+0

Jeffrey Richter trong cuốn sách "CLR Via C#, 3rd edition" đề cập đến các biến luôn được CLR khởi tạo thành 'null'. Ông cũng nói rằng thực sự nó không cần thiết cho trình biên dịch C# để cấm sử dụng các biến không khởi tạo, nhưng trình biên dịch vẫn có hạn chế này. –

3

"Nó phụ thuộc"

Đối với bình thường biến thành viên khi một giá trị không được xác định trong khai báo sau đó biến giả định giá trị mặc định thích hợp (null với nhiều loại tài liệu tham khảo). Tức là, class A { string X; } cũng giống như class A { string X = null; }.

Đối với biến cục bộ là lỗi khi truy cập chúng trước khi giá trị có thể được chứng minh là đã được chỉ định. Mặc dù kiểu "mặc định" của chúng là null (đối với các kiểu tham chiếu), chúng không được gán ngầm định mặc định! Tức là, string F() { string x; return x; } là lỗi biên dịch.

Hãy nhớ rằng: nullnull :-)

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