2010-01-06 30 views
6

Kiểm tra mã này ..Tại sao các loại tham chiếu không được khởi tạo thành null?

string str; 

    if (str.Contains("something..")) 
    { 
    } 

biên dịch ném lỗi này cho mã này

Sử dụng unassigned địa phương biến 'str'

Tại sao một loại tài liệu tham khảo không được khởi tạo để null?

Chỉ muốn biết sự tò mò.

Tôi cũng muốn biết điều gì xảy ra với mã bên dưới. cách phân công này hoạt động như thế nào?

string str = null; 

Trả lời

20

Chỉ lĩnh vực (các biến khai báo ở cấp lớp) đều được khởi tạo tự động:

  • loại giá trị được khởi tạo giá trị mặc định của họ.
  • Loại tham chiếu được khởi tạo thành tham chiếu null.

Điều bạn khai báo là "biến cục bộ" bên trong phương thức. Biến cục bộ không được tự động khởi chạy bất kể là loại giá trị hoặc loại tham chiếu.

Tôi cũng muốn biết điều gì xảy ra với mã bên dưới. cách phân công này hoạt động như thế nào?

tập này khởi tạo các biến địa phương với giá trị null với một lệnh ldnull theo sau là một hướng dẫn stloc (trong trường hợp nó không được tối ưu hóa ra, tất nhiên) và quan trọng hơn, thỏa mãn quy tắc phân tích luồng dữ liệu của trình biên dịch cho nhiệm vụ nhất định. Đặc tả C# định nghĩa một khái niệm được gọi là gán xác định để đảm bảo một biến được gán trước khi sử dụng lần đầu tiên.

+0

Bạn đang nói về các trường có kiểu tham chiếu và vẫn được khởi tạo là rỗng? Vậy tại sao lại khác biệt như vậy? –

+0

Sự khác biệt giữa những gì? Là địa phương hay không? –

+2

@Mehrdad: Tôi nghĩ anh ấy muốn biết tại sao các biến cục bộ không được tự động khởi tạo về giá trị mặc định của chúng như trái ngược với các trường. Lý do là vì điều này đã được tối ưu hóa. Trình biên dịch có thể nói một biến an toàn có được gán giá trị hay không. Nếu nó không phải là trình biên dịch sẽ ném một lỗi tại thời gian biên dịch. Tối ưu hóa này sẽ không thể cho các trường. –

-1

Hãy nhớ rằng việc gọi có chứa trên một chuỗi rỗng sẽ ném một NullReferenceException.

+0

điều này sẽ không biên dịch chút nào. –

+0

Tôi đoán là tôi đã hiểu nhầm. Tôi nghĩ bạn cũng đã hỏi điều gì sẽ xảy ra nếu bạn đã thiết lập mã biến str thành null. Trong trường hợp đó, ngoại lệ sẽ xảy ra. –

2

không được khởi tạo thành vô giá trị. Trình biên dịch chỉ làm bạn một ưu tiên bằng cách không phải gỡ lỗi NullReferenceException không thể tránh khỏi bạn sẽ nhận được.

+0

Mehrdad là đúng, biến địa phương không thực sự được khởi tạo, vì nó sẽ là vô nghĩa vì bạn không thể sử dụng biến cục bộ cho đến khi được gán giá trị, trình biên dịch sẽ không cho phép bạn :-) –

+0

Hmya, chicked and- vấn đề về trứng. Nó được cho phép trong VB.NET, nó không tạo ra bất kỳ IL nào để khởi tạo biến cục bộ. Khởi tạo được thực hiện bởi trình biên dịch JIT. –

+0

Khi thay đổi ví dụ trên để chỉ kiểm tra chuỗi cho null - bạn vẫn không thể biên dịch thành các vars chưa được khởi tạo, thậm chí không thể kiểm tra đối với null. Làm phiền tôi đôi khi khi chuyển đổi giữa C# và java. – FrankKrumnow

6

C# langauge yêu cầu tất cả các biến chắc chắn phải được gán trước khi chúng được đọc. Biến cục bộ được coi là ban đầu chưa được gán, trong khi các trường, thành phần mảng, v.v. được coi là ban đầu được gán cho giá trị mặc định. Không có lý do kỹ thuật nào tại sao chúng ta không thể xử lý các biến cục bộ như ban đầu được gán cho các giá trị mặc định của chúng và vứt bỏ tất cả việc kiểm tra phân định xác định. Nó có bởi vì sử dụng một địa phương chưa được gán làm giá trị mặc định của nó là (1) một thực hành mã hóa xấu, và (2) một nguồn có khả năng gây ra các lỗi kích thích cao.Bằng cách yêu cầu bạn chỉ định rõ ràng biến cục bộ trước khi chúng được sử dụng, chúng tôi ngăn người dùng sử dụng thực hành không tốt và loại bỏ toàn bộ lớp lỗi mà bạn không bao giờ phải gỡ lỗi.

Ngoài ra, hãy xem xét những điều sau đây:

while(whatever) 
{ 
    int i; 
    print(i); 
    i = i + 1; 
} 

Bạn có mong đợi tôi để giữ giá trị của nó trên khắp hành của vòng lặp, hoặc cho nó được khởi tạo trong lành về không mỗi lần? Bằng cách buộc bạn phải khởi tạo nó một cách rõ ràng, câu hỏi trở nên vô nghĩa và đây là một sự khác biệt không tạo ra sự khác biệt nào.

(Ngoài ra, trong trường hợp trên có tối ưu hiệu suất tiềm năng nhỏ, trong đó trình biên dịch có thể sử dụng lại biến mà không phải tạo mã để xóa nội dung của trình biên dịch vì trình biên dịch biết rằng bạn sẽ xóa nội dung .)

Tôi không biết cách trả lời câu hỏi thứ hai của bạn bởi vì tôi không biết ý bạn là "làm việc". Bạn có thể cho tôi biết cách gán "int x = 123;" công trinh? Một khi tôi biết những gì bạn có ý nghĩa của "công trình" sau đó tôi có thể mô tả cách gán một null cho một biến của loại tài liệu tham khảo hoạt động.

+0

Cần lưu ý rằng nếu người ta thay đổi dòng 'print' thành' OutsideObject.Print (out i); ', gọi một thường trình được viết bằng ngôn ngữ khác, trình biên dịch sẽ tự động tạo một cuộc gọi để đảm bảo rằng' i' sẽ được khởi tạo trước cuộc gọi đầu tiên, nhưng có thể hoặc không thể được khởi tạo trước cuộc gọi tiếp theo. Thật vậy, nếu 'zz' là một kiểu cấu trúc có hàm khởi tạo chuyển' this' này thành tham số 'out' sang mã ngoài, thậm chí một câu lệnh như' var foo = new zz (2); 'có thể không để' foo' hoàn toàn bị ảnh hưởng. – supercat

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