5

Tôi đã nhận thấy điều gì đó kỳ lạ về Visual Studio. Đầu tiên, hãy thử gõ lệnh (C#) ở đâu đó trong một hàm:Cảnh báo tham chiếu của Visual Studio null - tại sao không có lỗi?

class Foo 
{ 
    public void Bar() 
    { 
     string s; 
     int i = s.Length; 
    } 
} 

Bây giờ, ngay lập tức nó sẽ đánh dấu s trong s.Length như một lỗi, nói rằng "Use of unassigned local variable 's'". Mặt khác, hãy thử mã này:

class Foo 
{ 
    private string s; 
    public void Bar() 
    { 
     int i = s.Length; 
    } 
} 

Nó sẽ biên dịch, và nhấn mạnh s trong private string s với một cảnh báo, nói rằng "Field 'Foo.s' is never assigned to, and will always have its default value null".

Bây giờ, nếu VS là thông minh và biết rằng s sẽ luôn luôn là null, tại sao nó không phải là một lỗi để có được chiều dài của nó trong ví dụ thứ hai? Đoán ban đầu của tôi là, "Nó chỉ đưa ra một lỗi biên dịch nếu trình biên dịch chỉ đơn giản là không thể hoàn thành công việc của nó. Kể từ khi mã kỹ thuật chạy miễn là bạn không bao giờ gọi Bar(), nó chỉ là một cảnh báo." Ngoại trừ giải thích đó bị vô hiệu hóa bởi ví dụ đầu tiên. Bạn vẫn có thể chạy mã mà không có lỗi miễn là bạn không bao giờ gọi Bar(). Vì vậy, những gì cho? Chỉ là một sự giám sát, hay tôi đang thiếu một cái gì đó?

Trả lời

8

Ví dụ đầu tiên (lỗi) là ví dụ về theo dõi definite-assignment của Trình biên dịch và chỉ áp dụng cho các biến cục bộ. Do bối cảnh hạn chế, trình biên dịch có độ bám kín trên tình huống này. Lưu ý rằng s không phải là null, nó không được xác định.

Trong ví dụ thứ hai, s là trường (và mặc định là rỗng). Không có lỗi trình biên dịch, nhưng nó sẽ luôn luôn bị bắt khi chạy. Trường hợp cụ thể này có thể bị mắc kẹt nhưng loại lỗi này không thể phát hiện chung bởi trình biên dịch.
Ví dụ: bạn có thể thêm phương thức Bar2() gán một chuỗi cho s nhưng gọi nó sau Bar() hoặc hoàn toàn không. Điều đó sẽ loại bỏ cảnh báo nhưng không xóa lỗi thời gian chạy.

Vì vậy, theo thiết kế.

0

Dự đoán duy nhất tôi có thể thực hiện là trong ví dụ thứ hai, s có thể được thay đổi thông qua phản ánh (sử dụng BindingFlags.Private để truy cập thành viên riêng tư).

0

Trong mẫu đầu tiên s là biến cục bộ và trình biên dịch có thể easialy kiểm tra rằng s varible chưa được gán trước khi sử dụng.

Trong trường hợp thứ hai, s là biến toàn cầu và có thể nó đã được khởi tạo ở một nơi khác trong lớp học.

+0

s không toàn cầu, nó là một ví dụ -cánh đồng. –

3

Đối với ví dụ thứ hai, mã hợp lệ chỉ có thể không chạy đúng. Dưới đây là một số trường hợp trong đó chương trình này có thể thực thi "thành công"

  • Trình biên dịch không chính xác 100%. Có thể cho "s" có giá trị không null nếu một thể hiện được sửa đổi thông qua sự phản chiếu.
  • Chương trình có thể thực hiện mà không có lỗi nếu phương pháp Bar không bao giờ được gọi là
  • Chương trình này có thể là một chương trình thử nghiệm được kích hoạt một NullReferenceException vì lý do kiểm tra
Các vấn đề liên quan