0 Câu hỏi: Tại sao tôi nhận được tham chiếu Đối tượng không được đặt thành phiên bản của lỗi đối tượng? [bản sao]

câu hỏi được tạo ra tại Wed, May 8, 2019 12:00 AM

Tôi có một số mã và khi nó thực thi, nó sẽ ném NullReferenceException, nói:

  

Tham chiếu đối tượng không được đặt thành phiên bản của đối tượng.

Điều này có nghĩa là gì và tôi có thể làm gì để khắc phục lỗi này?

    
1877
  1. Trình trợ giúp ngoại lệ trong VS 2017 sẽ hữu ích hơn trong việc chẩn đoán nguyên nhân của ngoại lệ này - blog.msdn.microsoft.com/visualstudio/2016/11/11/trong Trình trợ giúp ngoại lệ mới .
    2016-12-29 09: 06: 19Z
  2. Các khách truy cập trong tương lai, câu trả lời cho câu hỏi này cũng áp dụng tương tự cho ArgumentNullException . Nếu câu hỏi của bạn đã bị đóng như là một bản sao của câu hỏi này và bạn đang gặp ANE, vui lòng làm theo hướng dẫn trong câu trả lời để gỡ lỗi và khắc phục sự cố của bạn.
    2017-10-13 17: 56: 23Z
  3. @ sẽ ANE chỉ xảy ra nếu null được truyền dưới dạng tham số. Bạn có thể đưa ra một ví dụ nếu câu hỏi ANE đóng như một bản sao của câu hỏi này không?
    2017-10-14 21: 44: 46Z
  4. Nó xuất hiện trên Meta, nhưng tôi phải đi đào liên kết. Nhưng theo nhận xét đó, ANE chỉ đơn giản là một NRE nhưng có ai đó đã thêm một kiểm tra phòng ngừa và ít nhất bạn biết chính xác null là gì (tên đối số được cung cấp), do đó, việc chẩn đoán dễ dàng hơn một chút so với NRE. /div>
    2017-10-16 12: 53: 02Z
    30 Câu trả lời                              30                         

    Nguyên nhân là gì?

    Dòng dưới

    Bạn đang cố gắng sử dụng một cái gì đó là null (hoặc Nothing trong VB.NET). Điều này có nghĩa là bạn đặt nó thành null hoặc bạn không bao giờ đặt nó thành bất cứ điều gì cả.

    Giống như mọi thứ khác, null được thông qua. Nếu là null trong phương thức "A", thì đó có thể là phương thức "B" đã truyền một phương thức null cho "A".

    null có thể có các ý nghĩa khác nhau:

    1. Các biến đối tượng chưa được khởi tạo và do đó trỏ đến không có gì. Trong trường hợp này, nếu bạn truy cập các thuộc tính hoặc phương thức của các đối tượng đó, nó sẽ gây ra NullReferenceException.
    2. Nhà phát triển đang sử dụng null để chỉ ra rằng không có giá trị có ý nghĩa. Lưu ý rằng C # có khái niệm về kiểu dữ liệu nullable cho các biến (như bảng cơ sở dữ liệu có thể có các trường không thể) đối với họ để chỉ ra rằng không có giá trị nào được lưu trữ trong đó, ví dụ null trong đó dấu hỏi cho biết nó được phép lưu trữ null trong biến int? a = null;. Bạn có thể kiểm tra xem với biến số a hay với 0600350991111010 để truy cập giá trị qua if (a.HasValue) {...} một cách rõ ràng hoặc chỉ như bình thường qua if (a==null) {...}.
      Lưu ý khi truy cập nó qua 060035099111100101350 tức là nếu bạn có một biến không có giá trị khác a thì bạn nên thực hiện các bài tập như a.Value hoặc ngắn hơn a.

    Phần còn lại của bài viết này đi sâu vào chi tiết hơn và chỉ ra những lỗi mà nhiều lập trình viên thường mắc phải có thể dẫn đến a.Value.

    Cụ thể hơn

    Thời gian chạy ném InvalidOperationException luôn có nghĩa tương tự: bạn đang cố sử dụng một tham chiếu và tham chiếu không được khởi tạo (hoặc nó được khởi tạo một lần , nhưng là không còn được khởi tạo).

    Điều này có nghĩa là tham chiếu là NullReferenceException và bạn không thể truy cập các thành viên (chẳng hạn nhưnhư các phương thức) thông qua một tham chiếu a. Trường hợp đơn giản nhất:

    null

    Điều này sẽ ném int b; ở dòng thứ hai vì bạn không thể gọi phương thức cá thể if (a.HasValue) { b = a.Value; } trên tham chiếu if (a != null) { b = a; } trỏ đến NullReferenceException.

    Gỡ lỗi

    Làm thế nào để bạn tìm thấy nguồn của NullReferenceException? Ngoài việc xem xét chính ngoại lệ, sẽ được ném chính xác tại vị trí xảy ra, các quy tắc gỡ lỗi chung trong Visual Studio được áp dụng: đặt các điểm dừng chiến lược và kiểm tra các biến của bạn , bằng cách di chuột qua tên của chúng, mở cửa sổ Xem nhanh (Quick) hoặc sử dụng các bảng gỡ lỗi khác nhau như Locals và Autos.

    Nếu bạn muốn tìm nơi tham chiếu được đặt hoặc không được đặt, hãy nhấp chuột phải vào tên của nó và chọn "Tìm tất cả tài liệu tham khảo". Sau đó, bạn có thể đặt một điểm dừng ở mọi vị trí tìm thấy và chạy chương trình của bạn với trình gỡ lỗi được đính kèm. Mỗi khi trình gỡ lỗi phá vỡ điểm dừng như vậy, bạn cần xác định xem bạn có mong muốn tham chiếu là không null hay không, kiểm tra biến và xác minh rằng nó trỏ đến một thể hiện khi bạn mong đợi nó.

    Bằng cách theo dòng chảy chương trình theo cách này, bạn có thể tìm thấy vị trí mà trường hợp không nên rỗng và tại sao nó không được đặt đúng.

    Ví dụ

    Một số tình huống phổ biến có thể ném ngoại lệ:

    Chung

    null

    Nếu ref1 hoặc ref2 hoặc ref3 là null, thì bạn sẽ nhận được null. Nếu bạn muốn giải quyết vấn đề, hãy tìm ra cái nào là null bằng cách viết lại biểu thức thành tương đương đơn giản hơn:

    string foo = null;
    foo.ToUpper();
    

    Cụ thể, trong NullReferenceException, ToUpper() có thể là null hoặc tài sản string có thể là null hoặc tài sản null có thể là null.

    Gián tiếp

    NullReferenceException

    Nếu bạn muốn tránh tham chiếu null (Person) con, bạn có thể khởi tạo nó trong hàm tạo của đối tượng cha mẹ (Sách).

    Công cụ khởi tạo đối tượng lồng nhau

    Áp dụng tương tự cho các trình khởi tạo đối tượng lồng nhau:

    ref1.ref2.ref3.member
    

    Điều này dịch thành

    NullReferenceException .

    Công cụ khởi tạo bộ sưu tập lồng nhau

    var r1 = ref1;
    var r2 = r1.ref2;
    var r3 = r2.ref3;
    r3.member
    

    Công cụ khởi tạo bộ sưu tập lồng nhau hoạt động giống nhau:

    HttpContext.Current.User.Identity.Name

    Điều này dịch thành

    HttpContext.Current

    User chỉ tạo một phiên bản Identity, nhưng bộ sưu tập

    public class Person {
        public int Age { get; set; }
    }
    public class Book {
        public Person Author { get; set; }
    }
    public class Example {
        public void Foo() {
            Book b1 = new Book();
            int authorAge = b1.Author.Age; // You never initialized the Author property.
                                           // there is no Person to get an Age from.
        }
    }
    
    vẫn là
    Book b1 = new Book { Author = { Age = 45 } };
    
    . Cú pháp khởi tạo bộ sưu tập không tạo ra bộ sưu tập đối với
    Book b1 = new Book();
    b1.Author.Age = 45;
    
    , nó chỉ chuyển thành các câu lệnh new.

    Mảng

    Book

    Các phần tử mảng

    Person

    Mảng răng cưa

    Author

    Bộ sưu tập /Danh sách /Từ điển

    null

    Biến phạm vi (gián tiếp /hoãn)

    public class Person {
        public ICollection<Book> Books { get; set; }
    }
    public class Book {
        public string Title { get; set; }
    }
    

    Sự kiện

    Person p1 = new Person {
        Books = {
            new Book { Title = "Title1" },
            new Book { Title = "Title2" },
        }
    };
    

    Các quy ước đặt tên xấu:

    Nếu bạn đặt tên các trường khác với người địa phương, bạn có thể nhận ra rằng bạn chưa bao giờ khởi tạo trường.

    Person p1 = new Person();
    p1.Books.Add(new Book { Title = "Title1" });
    p1.Books.Add(new Book { Title = "Title2" });
    

    Điều này có thể được giải quyết bằng cách tuân theo quy ước đối với các trường tiền tố có dấu gạch dưới:

    new Person

    Vòng đời trang ASP.NET:

    Person

    Giá trị phiên ASP.NET

    Books

    Mô hình xem trống ASP.NET MVC

    Nếu ngoại lệ xảy ra khi tham chiếu thuộc tính null trong chế độ xem ASP.NET MVC, bạn cần hiểu rằng p1.Books được đặt trong phương thức hành động của bạn, khi bạn xem p1.Books.Add(...). Khi bạn trả về một mô hình trống (hoặc thuộc tính mô hình) từ bộ điều khiển của bạn, ngoại lệ xảy ra khi các khung nhìn truy cập vào nó:

    int[] numbers = null;
    int n = numbers[0]; // numbers is null. There is no array to index.
    

    Thứ tự và sự kiện tạo điều khiển WPF

    Các điều khiển WPF được tạo trong cuộc gọi đến

    Person[] people = new Person[5];
    people[0].Age = 20 // people[0] is null. The array was allocated but not
                       // initialized. There is no Person to set the Age for.
    
    theo thứ tự chúng xuất hiện trong cây trực quan. Một
    long[][] array = new long[1][];
    array[0][0] = 3; // is null because only the first dimension is yet initialized.
                     // Use array[0] = new long[2]; first.
    
    sẽ được nâng lên trong trường hợp các điều khiển được tạo sớm với các trình xử lý sự kiện, v.v., bắn trong
    Dictionary<string, int> agesForNames = null;
    int age = agesForNames["Bob"]; // agesForNames is null.
                                   // There is no Dictionary to perform the lookup.
    
    tham chiếu các điều khiển được tạo muộn.

    Ví dụ:

    public class Person {
        public string Name { get; set; }
    }
    var people = new List<Person>();
    people.Add(null);
    var names = from p in people select p.Name;
    string firstName = names.First(); // Exception is thrown here, but actually occurs
                                      // on the line above.  "p" is null because the
                                      // first element we added to the list is null.
    

    Tại đây

    public class Demo
    {
        public event EventHandler StateChanged;
    
        protected virtual void OnStateChanged(EventArgs e)
        {        
            StateChanged(this, e); // Exception is thrown here 
                                   // if no event handlers have been attached
                                   // to StateChanged event
        }
    }
    
    được tạo trước
    public class Form1 {
        private Customer customer;
    
        private void Form1_Load(object sender, EventArgs e) {
            Customer customer = new Customer();
            customer.Name = "John";
        }
    
        private void Button_Click(object sender, EventArgs e) {
            MessageBox.Show(customer.Name);
        }
    }
    
    . Nếu
    private Customer _customer;
    
    cố gắng tham chiếu `nhãn1, nó sẽ chưa được tạo.
    public partial class Issues_Edit : System.Web.UI.Page
    {
        protected TestIssue myIssue;
    
        protected void Page_Load(object sender, EventArgs e)
        {
            if (!IsPostBack)
            {
                // Only called on first load, not when button clicked
                myIssue = new TestIssue(); 
            }
        }
    
        protected void SaveButton_Click(object sender, EventArgs e)
        {
            myIssue.Entry = "NullReferenceException here!";
        }
    }
    

    Thay đổi thứ tự khai báo trong XAML (tức là, liệt kê

    // if the "FirstName" session value has not yet been set,
    // then this line will throw a NullReferenceException
    string firstName = Session["FirstName"].ToString();
    
    trước @Model, bỏ qua các vấn đề về triết lý thiết kế, ít nhất sẽ giải quyết Model tại đây.

    Truyền với return

    // Controller
    public class Restaurant:Controller
    {
        public ActionResult Search()
        {
             return View();  // Forgot the provide a Model here.
        }
    }
    
    // Razor view 
    @foreach (var restaurantSearch in Model.RestaurantSearch)  // Throws.
    {
    }
    
    <p>@Model.somePropertyName</p> <!-- Also throws -->
    

    Điều này không ném UnlimitedCastException nhưng trả về InitializeComponent khi diễn viên thất bại (và khi someObject tự nó là null). Vì vậy, hãy nhận thức về điều đó.

    LINQ FirstOrDefault () và SingleOrDefault ()

    Các phiên bản đơn giản NullReferenceExceptionInitializeComponent ném ngoại lệ khi không có gì. Các phiên bản "OrDefault" trả về null trong trường hợp đó. Vì vậy, hãy nhận thức về điều đó.

    thuyết minh

    <Grid>
        <!-- Combobox declared first -->
        <ComboBox Name="comboBox1" 
                  Margin="10"
                  SelectedIndex="0" 
                  SelectionChanged="comboBox1_SelectionChanged">
            <ComboBoxItem Content="Item 1" />
            <ComboBoxItem Content="Item 2" />
            <ComboBoxItem Content="Item 3" />
        </ComboBox>
    
        <!-- Label declared later -->
        <Label Name="label1" 
               Content="Label"
               Margin="10" />
    </Grid>
    
    ném khi bạn cố gắng lặp lại bộ sưu tập null. Thường gây ra bởi kết quả không mong muốn comboBox1 từ các phương thức trả về bộ sưu tập. label1

    Ví dụ thực tế hơn - chọn các nút từ tài liệu XML. Sẽ ném nếu các nút không được tìm thấy nhưng gỡ lỗi ban đầu cho thấy tất cả các thuộc tính hợp lệ:

    comboBox1_SelectionChanged

    Những cách tránh

    Kiểm tra rõ ràng
    private void comboBox1_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        label1.Content = comboBox1.SelectedIndex.ToString(); // NullReference here!!
    }
    
    và bỏ qua các giá trị null.

    Nếu đôi khi bạn cho rằng tham chiếu là null, bạn có thể kiểm tra xem nó có phải là label1 trước khi truy cập các thành viên thể hiện:

    comboBox1

    Kiểm tra rõ ràng NullReferenceException và cung cấp giá trị mặc định.

    Các phương thức gọi mà bạn mong đợi trả về một thể hiện có thể trả về as, ví dụ khi không thể tìm thấy đối tượng đang tìm kiếm. Bạn có thể chọn trả về giá trị mặc định khi gặp trường hợp này:

    var myThing = someObject as Thing;
    

    Kiểm tra rõ ràng null từ các cuộc gọi phương thức và ném ngoại lệ tùy chỉnh.

    Bạn cũng có thể ném ngoại lệ tùy chỉnh, chỉ để bắt nó trong mã cuộc gọi:

    First()

    Sử dụng Single() nếu giá trị không bao giờ là foreach, để bắt sự cố sớm hơn ngoại lệ xảy ra.

    Khi bạn biết trong quá trình phát triển, một phương thức có thể có thể, nhưng không bao giờ nên trả về null, bạn có thể sử dụng

     List<int> list = null;    
     foreach(var v in list) { } // exception
    
    để phá vỡ càng sớm càng tốt khi nó xảy ra:
     foreach (var node in myData.MyXml.DocumentNode.SelectNodes("//Data"))
    

    Mặc dù kiểm tra này sẽ không kết thúc trong bản dựng phát hành của bạn , gây ra nó sẽ ném null một lần nữa khi null khi chạy ở chế độ phát hành.

    Sử dụng
    void PrintName(Person p) {
        if (p != null) {
            Console.WriteLine(p.Name);
        }
    }
    
    cho các loại giá trị không thể cung cấp giá trị mặc định khi chúng là null.

    null

    Sử dụng toán tử hợp nhất null:
    string GetCategory(Book b) {
        if (b == null)
            return "Unknown";
        return b.Category;
    }
    
    [C #] hoặc null [VB].

    Tốc ký để cung cấp giá trị mặc định khi gặp phải

    string GetCategory(string bookTitle) {
        var book = library.FindBook(bookTitle);  // This may return null
        if (book == null)
            throw new BookNotFoundException(bookTitle);  // Your custom exception
        return book.Category;
    }
    
    : Debug.Assert

    Sử dụng toán tử điều kiện null: null hoặc null cho mảng (có sẵn trong C # 6 và VB.NET 14):

    Điều này đôi khi cũng được gọi là toán tử điều hướng an toàn hoặc toán tử Elvis (sau hình dạng của nó). Nếu biểu thức ở phía bên trái của toán tử là null, thì phía bên phải sẽ không được ước tính và thay vào đó null được trả về. Điều đó có nghĩa là những trường hợp như thế này:

    Debug.Assert()

    Nếu người đó không có tiêu đề, điều này sẽ đưa ra một ngoại lệ vì họ đang cố gắng gọi

    string GetTitle(int knownBookID) {
        // You know this should never return null.
        var book = library.GetBook(knownBookID);  
    
        // Exception will occur on the next line instead of at the end of this method.
        Debug.Assert(book != null, "Library didn't return a book for known book ID.");
    
        // Some other code
    
        return book.Title; // Will never throw NullReferenceException in Debug mode.
    }
    
    trên một tài sản có giá trị null.

    Trong C # 5 trở xuống, điều này có thể được bảo vệ bằng:

    NullReferenceException

    Bây giờ biến tiêu đề sẽ là null thay vì ném một ngoại lệ. C # 6 giới thiệu một cú pháp ngắn hơn cho việc này:

    book == null

    Điều này sẽ dẫn đến biến tiêu đề là GetValueOrDefault() và cuộc gọi đến null không được thực hiện nếu

    DateTime? appointment = null;
    Console.WriteLine(appointment.GetValueOrDefault(DateTime.Now));
    // Will display the default value provided (DateTime.Now), because appointment is null.
    
    appointment = new DateTime(2022, 10, 20);
    Console.WriteLine(appointment.GetValueOrDefault(DateTime.Now));
    // Will display the appointment date, not the default
    
    ??.

    Tất nhiên, bạn vẫn phải kiểm tra If() để tìm null hoặc sử dụng toán tử điều kiện null cùng với toán tử hợp nhất null (null) để cung cấp giá trị mặc định:

    IService CreateService(ILogger log, Int32? frobPowerLevel)
    {
        var serviceImpl = new MyService(log ?? NullLog.Instance);
    
        // Note that the above "GetValueOrDefault()" can also be rewritten to use
        // the coalesce operator:
        serviceImpl.FrobPowerLevel = frobPowerLevel ?? 5;
    }
    

    Tương tự như vậy, đối với các mảng, bạn có thể sử dụng ?. như sau:

    ?[x]

    Điều này sẽ làm như sau: Nếu myIntArray là null, biểu thức trả về null và bạn có thể kiểm tra nó một cách an toàn. Nếu nó chứa một mảng, nó sẽ làm như sau:

    var title = person.Title.ToUpper();
    
    và trả về phần tử i th .

    Các kỹ thuật đặc biệt để gỡ lỗi và sửa lỗi null derefs trong các trình vòng lặp

    C # hỗ trợ "khối lặp" (được gọi là "trình tạo" trong một số ngôn ngữ phổ biến khác). Các trường hợp ngoại lệ của Null có thể đặc biệt khó khăn để gỡ lỗi trong các khối lặp vì thực thi bị trì hoãn:

    ToUpper

    Nếu

    var title = person.Title == null ? null : person.Title.ToUpper();
    
    kết quả trong
    var title = person.Title?.ToUpper();
    
    thì null sẽ ném. Bây giờ, bạn có thể nghĩ rằng điều đúng đắn cần làm là: ToUpper

    Tại sao điều này sai?Bởi vì khối lặp không thực sự chạy cho đến person.Title! Cuộc gọi đến null chỉ đơn giản trả về một đối tượng mà khi lặp sẽ chạy khối lặp.

    Bằng cách viết một kiểm tra null như thế này, bạn sẽ ngăn chặn sự hủy bỏ null, nhưng bạn di chuyển ngoại lệ đối số null đến điểm của lặp , không đến điểm của cuộc gọi và đó là rất khó hiểu để gỡ lỗi .

    Cách khắc phục chính xác là:

    title

    Nghĩa là tạo một phương thức trợ giúp riêng có logic khối lặp và một phương thức bề mặt công khai kiểm tra null và trả về iterator. Bây giờ khi ?? được gọi, kiểm tra null sẽ xảy ra ngay lập tức và sau đó

    // regular null check
    int titleLength = 0;
    if (title != null)
        titleLength = title.Length; // If title is null, this would throw NullReferenceException
    
    // combining the `?` and the `??` operator
    int titleLength = title?.Length ?? 0;
    
    thực thi khi trình tự được lặp lại.

    Nếu bạn kiểm tra nguồn tham chiếu cho LINQ đến các Đối tượng, bạn sẽ thấy kỹ thuật này được sử dụng xuyên suốt. Nó hơi khó viết hơn một chút, nhưng nó làm cho việc sửa lỗi vô hiệu hóa dễ dàng hơn nhiều. Tối ưu hóa mã của bạn để thuận tiện cho người gọi, không phải là sự tiện lợi của tác giả .

    Một lưu ý về các cuộc hội thảo null trong mã không an toàn

    C # có chế độ "không an toàn", đúng như tên gọi, cực kỳ nguy hiểm vì các cơ chế an toàn thông thường cung cấp an toàn bộ nhớ và an toàn loại không được thi hành. Bạn không nên viết mã không an toàn trừ khi bạn hiểu rõ và sâu sắc về cách thức hoạt động của bộ nhớ .

    Ở chế độ không an toàn, bạn cần lưu ý đến hai sự thật quan trọng:

    • hủy bỏ hội thảo một con trỏ null tạo ra ngoại lệ tương tự như việc hủy bỏ tham chiếu null tham chiếu
    • hủy bỏ một con trỏ không null không hợp lệ có thể tạo ra ngoại lệ đó trong một số trường hợp

    Để hiểu lý do tại sao, điều đó giúp hiểu cách .NET tạo ra các ngoại lệ vô hiệu hóa null ngay từ đầu. (Các chi tiết này áp dụng cho .NET chạy trên Windows; các hệ điều hành khác sử dụng các cơ chế tương tự.)

    Bộ nhớ được ảo hóa trong Windows; mỗi tiến trình có một không gian bộ nhớ ảo gồm nhiều "trang" bộ nhớ được hệ điều hành theo dõi. Mỗi trang của bộ nhớ có các cờ được đặt trên đó để xác định cách sử dụng: đọc từ, ghi vào, thực thi, v.v. Trang thấp nhất được đánh dấu là "tạo ra lỗi nếu được sử dụng theo bất kỳ cách nào".

    Cả con trỏ null và tham chiếu null trong C # đều được biểu thị bên trong dưới dạng số 0 và do đó, bất kỳ nỗ lực nào để đưa nó vào bộ nhớ tương ứng của nó đều khiến hệ điều hành gây ra lỗi. Thời gian chạy .NET sau đó phát hiện lỗi này và biến nó thành ngoại lệ vô hiệu hóa null.

    Đó là lý do tại sao hội thảo cả con trỏ null và tham chiếu null tạo ra cùng một ngoại lệ.

    Còn điểm thứ hai thì sao? Dereferences any con trỏ không hợp lệ rơi vào trang thấp nhất của bộ nhớ ảo gây ra lỗi hệ điều hành tương tự và do đó cũng có ngoại lệ tương tự.

    Tại sao điều này có ý nghĩa? Chà, giả sử chúng ta có một cấu trúc chứa hai số nguyên và một con trỏ không được quản lý bằng null. Nếu chúng tôi cố gắng hủy đăng ký int thứ hai trong cấu trúc, CLR sẽ không cố truy cập vào bộ lưu trữ ở vị trí 0; nó sẽ truy cập vào bộ lưu trữ tại vị trí bốn. Nhưng về mặt logic, đây là một sự vô hiệu hóa bởi vì chúng tôi đang đến địa chỉ đó thông qua null.

    Nếu bạn đang làm việc với mã không an toàn và bạn nhận được ngoại lệ vô hiệu hóa null, chỉ cần lưu ý rằng con trỏ vi phạm không cần phải là null. Nó có thể là bất kỳ vị trí nào trong trang thấp nhất và ngoại lệ này sẽ được tạo ra.

        
    2258
    2018-07-18 06: 27: 33Z
    1. Có thể đây là một nhận xét ngu ngốc nhưng không phải là cách đầu tiên và tốt nhất để tránh vấn đề này là khởi tạo đối tượng? Đối với tôi nếu lỗi này xảy ra thường là do tôi quên khởi tạo một cái gì đó như phần tử mảng. Tôi nghĩ rằng nó ít phổ biến hơn để định nghĩa đối tượng là null và sau đó tham chiếu nó. Có thể đưa ra cách giải quyết từng vấn đề liền kề với mô tả. Vẫn là một bài viết tốt.
      2014-05-20 06: 39: 13Z
    2. Điều gì xảy ra nếu không có đối tượng, mà là giá trị trả về từ một phương thức hoặc thuộc tính?
      2014-05-20 06: 41: 02Z
    3. Ví dụ về cuốn sách /tác giả hơi kỳ lạ .... Làm thế nào mà nó thậm chí còn biên dịch? Làm thế nào để intellisense thậm chí làm việc? Điều này là gì tôi không tốt với máy tính ...
      2014-09-08 18: 26: 23Z
    4. @ Will: lần chỉnh sửa cuối cùng của tôi có giúp được không? Nếu không, xin vui lòng nói rõ hơn về những gì bạn thấy là một vấn đề.
      2014-09-08 18: 41: 50Z
    5. @ JohnSaunders Ồ, không, xin lỗi, ý tôi là phiên bản khởi tạo đối tượng của điều đó. ?[i] Làm thế nào để khởi tạo bên trong thậm chí ... Tôi không thể nghĩ đến một tình huống mà init bên trong sẽ hoạt động, nhưng nó biên dịch và intellisense hoạt động ... Trừ khi có cấu trúc?
      2014-09-08 18: 44: 35Z

      Ngoại lệ NullReference - Visual Basic

      int[] myIntArray=null;
      var i=5;
      int? elem = myIntArray?[i];
      if (!elem.HasValue) Console.WriteLine("No value");
      
      cho Visual Basic không khác với cái trong C # . Rốt cuộc, cả hai đều báo cáo cùng một ngoại lệ được xác định trong .NET Framework mà cả hai đều sử dụng. Nguyên nhân duy nhất đối với Visual Basic là rất hiếm (có lẽ chỉ có một).

      Câu trả lời này sẽ sử dụng thuật ngữ, cú pháp và ngữ cảnh của Visual Basic. Các ví dụ được sử dụng đến từ một số lượng lớn các câu hỏi Stack Overflow trước đây. Điều này là để tối đa hóa mức độ liên quan bằng cách sử dụng loại của các tình huống thường thấy trong các bài đăng. Một chút giải thích cũng được cung cấp cho những người có thể cần nó. Một ví dụ tương tự như của bạn là rất có thể được liệt kê ở đây.

      Lưu ý:

      1. Đây là dựa trên khái niệm: không có mã để bạn dán vào dự án của mình. Nó nhằm giúp bạn hiểu nguyên nhân gây ra elem = myIntArray[i]; (NRE), cách tìm, cách khắc phục và cách tránh. Một NRE có thể được gây ra theo nhiều cách vì vậy đây không chắc là cuộc gặp gỡ duy nhất của bạn.
      2. Các ví dụ (từ bài đăng Stack Overflow) không phải lúc nào cũng hiển thị cách tốt nhất để làm điều gì đó ở vị trí đầu tiên.
      3. Thông thường, biện pháp khắc phục đơn giản nhất được sử dụng.

      Ý nghĩa cơ bản

      Thông báo "Đối tượng không được đặt thành phiên bản của Đối tượng" có nghĩa là bạn đang cố gắng sử dụng một đối tượng chưa được khởi tạo. Điều này làm sôi một trong những điều sau:

      • Mã của bạn đã khai báo một biến đối tượng, nhưng nó không khởi tạo nó (tạo một thể hiện hoặc ' khởi tạo ' nó)
      • Một cái gì đó mà mã của bạn giả định sẽ khởi tạo một đối tượng, không
      • Có thể, mã khác bị vô hiệu hóa sớm một đối tượng vẫn đang được sử dụng

      Tìm nguyên nhân

      Vì vấn đề là một tham chiếu đối tượng là

      public IEnumerable<Frob> GetFrobs(FrobFactory f, int count)
      {
          for (int i = 0; i < count; ++i)
            yield return f.MakeFrob();
      }
      ...
      FrobFactory factory = whatever;
      IEnumerable<Frobs> frobs = GetFrobs();
      ...
      foreach(Frob frob in frobs) { ... }
      
      , câu trả lời là kiểm tra chúng để tìm ra cái nào. Sau đó xác định lý do tại sao nó không được khởi tạo. Giữ chuột trên các biến khác nhau và Visual Studio (VS) sẽ hiển thị giá trị của chúng - thủ phạm sẽ là whatever.

      Hiển thị gỡ lỗi IDE

      Bạn cũng nên xóa mọi khối Thử /Bắt khỏi mã có liên quan, đặc biệt là các khối không có gì trong khối Bắt. Điều này sẽ khiến mã của bạn bị sập khi nó cố sử dụng một đối tượng là null. Đây là điều bạn muốn vì nó sẽ xác định chính xác vị trí của vấn đề bạn xác định đối tượng gây ra nó.

      A MakeFrob trong Catch hiển thị

      // DON'T DO THIS
      public IEnumerable<Frob> GetFrobs(FrobFactory f, int count)
      {
          if (f == null) 
            throw new ArgumentNullException("f", "factory must not be null");
          for (int i = 0; i < count; ++i)
            yield return f.MakeFrob();
      }
      
      sẽ giúp ích rất ít. Phương pháp này cũng dẫn đến các câu hỏi rất tệ Stack Overflow, bởi vì bạn không thể mô tả ngoại lệ thực tế, đối tượng liên quan hoặc thậm chí dòng mã nơi nó xảy ra.

      Bạn cũng có thể sử dụng foreach ( Gỡ lỗi - > Windows - > Người địa phương ) để kiểm tra các đối tượng của bạn.

      Khi bạn đã biết vấn đề là gì và ở đâu, thường khá dễ khắc phục và nhanh hơn so với việc đăng câu hỏi mới.

      Xem thêm:

      Ví dụ và biện pháp khắc phục

      Đối tượng lớp /Tạo một thực thể

      GetFrobs

      Vấn đề là

      // DO THIS
      public IEnumerable<Frob> GetFrobs(FrobFactory f, int count)
      {
          // No yields in a public method that throws!
          if (f == null) 
            throw new ArgumentNullException("f", "factory must not be null");
          return GetFrobsForReal(f, count);
      }
      private IEnumerable<Frob> GetFrobsForReal(FrobFactory f, int count)
      {
          // Yields in a private method
          Debug.Assert(f != null);
          for (int i = 0; i < count; ++i)
            yield return f.MakeFrob();
      }
      
      không tạo đối tượng CashRegister ; nó chỉ khai báo một biến có tên GetFrobs của Loại đó. Khai báo một biến đối tượng và tạo một thể hiện là hai điều khác nhau.

      Biện pháp

      Toán tử GetFrobsForReal thường có thể được sử dụng để tạo cá thể khi bạn khai báo:

      new Book { Author = { Age = 45 } };

      Khi nó chỉ phù hợp vớitạo ví dụ sau:

      NullReference Exception

      Lưu ý: Không sử dụng lại NullReferenceException trong quy trình, bao gồm cả công cụ xây dựng (Nothing):

      Nothing

      Điều này sẽ tạo ra một biến cục bộ , Nothing, chỉ tồn tại trong bối cảnh đó (phụ). Biến MsgBox với cấp mô-đun Error while... mà bạn sẽ sử dụng ở mọi nơi khác vẫn là Locals Window.

        

      Thiếu toán tử

      Dim reg As CashRegister
      ...
      TextBox1.Text = reg.Amount         ' NRE
      
      là nguyên nhân số 1 của Dim được thấy trong các câu hỏi về Stack Overflow được xem xét.

           

      Visual Basic cố gắng làm cho quá trình rõ ràng lặp đi lặp lại bằng cách sử dụng reg : Sử dụng toán tử 060035099111100135035062 tạo một đối tượng mới và gọi 060035099 - hàm tạo - nơi đối tượng của bạn có thể thực hiện bất kỳ khởi tạo nào khác.

      Để rõ ràng, New (hoặc

      Dim reg As New CashRegister        ' [New] creates instance, invokes the constructor
      
      ' Longer, more explicit form:
      Dim reg As CashRegister = New CashRegister
      
      ) chỉ khai báo một biến và
      Private reg As CashRegister         ' Declare
        ...
      reg = New CashRegister()            ' Create instance
      
      . Phạm vi của biến đó - cho dù nó tồn tại cho toàn bộ mô-đun là cục bộ của một thủ tục - được xác định bởi trong đó nó được khai báo. Dim xác định cấp độ truy cập, không phải Phạm vi .

      Để biết thêm thông tin, hãy xem:

      Mảng

      Mảng cũng phải được khởi tạo:

      Sub New

      Mảng này chỉ được khai báo, chưa được tạo. Có một số cách để khởi tạo một mảng:

      Private reg As CashRegister
      '...
      
      Public Sub New()
         '...
         Dim reg As New CashRegister
      End Sub
      

      Lưu ý: Bắt đầu với VS 2010, khi khởi tạo một mảng cục bộ bằng chữ và reg, regScope là các tùy chọn:

      Nothing

      Kiểu dữ liệu và kích thước mảng được suy ra từ dữ liệu được gán. Khai báo cấp độ lớp /mô-đun vẫn yêu cầu New với NullReference Exceptions:

      New

      Ví dụ: Mảng các đối tượng lớp

      New

      Mảng đã được tạo, nhưng các đối tượng Sub New không có.

      Biện pháp

      Dim

      Sử dụng Private sẽ khiến việc có một phần tử không có đối tượng hợp lệ:

      khá khó khăn. Type

      Để biết thêm thông tin, hãy xem:

      Danh sách và Bộ sưu tập

      Bộ sưu tập .NET (trong đó có nhiều loại - Danh sách, Từ điển, v.v.) cũng phải được khởi tạo hoặc tạo.

      Private | Friend | Public

      Bạn nhận được cùng một ngoại lệ vì cùng một lý do -

      Private arr as String()
      
      chỉ được khai báo, nhưng không có trường hợp nào được tạo. Biện pháp khắc phục là như nhau:
      Private arr as String() = New String(10){}
      ' or
      Private arr() As String = New String(10){}
      
      ' For a local array (in a procedure) and using 'Option Infer':
      Dim arr = New String(10) {}
      

      Một giám sát chung là một lớp sử dụng bộ sưu tập Option Infer:

      As <Type>

      Cả hai thủ tục sẽ dẫn đến một NRE, vì New chỉ được khai báo, không được khởi tạo. Tạo một thể hiện của

      Dim myDbl As Double() = {1.5, 2, 9.9, 18, 3.14}
      Dim myDbl = New Double() {1.5, 2, 9.9, 18, 3.14}
      Dim myDbl() = {1.5, 2, 9.9, 18, 3.14}
      
      cũng sẽ không tạo ra một thể hiện của As <Type> bên trong. Đây có thể là ý định thực hiện điều này trong hàm tạo: Option Strict

      Như trước đây, điều này không chính xác:

      Private myDoubles As Double() = {1.5, 2, 9.9, 18, 3.14}
      

      Để biết thêm thông tin, hãy xem

      Dim arrFoo(5) As Foo
      
      For i As Integer = 0 To arrFoo.Count - 1
         arrFoo(i).Bar = i * 10       ' Exception
      Next
      
      Lớp .

      Đối tượng nhà cung cấp dữ liệu

      Làm việc với cơ sở dữ liệu mang lại nhiều cơ hội cho NullReference vì có thể có nhiều đối tượng (Foo,

      For i As Integer = 0 To arrFoo.Count - 1
          arrFoo(i) = New Foo()         ' Create Foo instance
          arrFoo(i).Bar = i * 10
      Next
      
      , List(Of T),
      Dim FooList As New List(Of Foo)     ' List created, but it is empty
      Dim f As Foo                        ' Temporary variable for the loop
      
      For i As Integer = 0 To 5
          f = New Foo()                    ' Foo instance created
          f.Bar =  i * 10
          FooList.Add(f)                   ' Foo object added to list
      Next
      
      ,
      Private myList As List(Of String)
      ..
      myList.Add("ziggy")           ' NullReference
      
      , myList ....) đang sử dụng cùng một lúc. Lưu ý: Không quan trọng bạn đang sử dụng nhà cung cấp dữ liệu nào - MySQL, SQL Server, OleDB, v.v. - khái niệm giống nhau.

      Ví dụ 1

      myList = New List(Of String)
      
      ' Or create an instance when declared:
      Private myList As New List(Of String)
      

      Như trước đây, đối tượng Dataset Type đã được khai báo, nhưng một trường hợp không bao giờ được tạo.

      Public Class Foo
          Private barList As List(Of Bar)
      
          Friend Function BarCount As Integer
              Return barList.Count
          End Function
      
          Friend Sub AddItem(newBar As Bar)
              If barList.Contains(newBar) = False Then
                  barList.Add(newBar)
              End If
          End Function
      
      sẽ điền vào barList hiện tại, không tạo một. Trong trường hợp này, vì Foo là biến cục bộ, IDE cảnh báo bạn rằng điều này có thể xảy ra:

      img

      Khi được khai báo là biến cấp mô-đun /lớp, dường như là trường hợp với barList, trình biên dịch không thể biết liệu đối tượng có được tạo bởi thủ tục ngược dòng hay không. Đừng bỏ qua các cảnh báo.

      Biện pháp

      Public Sub New         ' Constructor
          ' Stuff to do when a new Foo is created...
          barList = New List(Of Bar)
      End Sub
      

      Ví dụ 2

      Public Sub New()
          ' Creates another barList local to this procedure
           Dim barList As New List(Of Bar)
      End Sub
      
      . Một vấn đề tiềm năng khác là giả sử sẽ có List(Of T) có thể không phải như vậy khi SQL bao gồm mệnh đề WHERE.

      Biện pháp

      Vì việc này sử dụng một bảng, sử dụng Command sẽ tránh được lỗi chính tả. Kiểm tra Connection cũng có thể giúp:

      Transaction

      Dataset là một hàm trả về số DataTable cũng có thể được kiểm tra:

      DataRows

      Ví dụ 3

      Dim da As OleDbDataAdapter
      Dim ds As DataSet
      Dim MaxRows As Integer
      
      con.Open()
      Dim sql = "SELECT * FROM tblfoobar_List"
      da = New OleDbDataAdapter(sql, con)
      da.Fill(ds, "foobar")
      con.Close()
      
      MaxRows = ds.Tables("foobar").Rows.Count      ' Error
      

      ds sẽ cung cấp DataAdapter như trong ví dụ trước, nhưng nó không phân tích tên từ bảng SQL hoặc cơ sở dữ liệu. Do đó, DataSet tham chiếu một bảng không tồn tại.

      Biện pháp giống nhau, tham chiếu bảng theo chỉ mục:

      ds

      Xem thêm Lớp DataTable .

      Đường dẫn đối tượng /lồng nhau

      con

      Mã chỉ đang thử nghiệm

      Dim ds As New DataSet
      
      trong khi cả
      ds = New DataSet
      da = New OleDBDataAdapter(sql, con)
      da.Fill(ds, "Employees")
      
      txtID.Text = ds.Tables("Employee").Rows(0).Item(1)
      txtID.Name = ds.Tables("Employee").Rows(0).Item(2)
      
      Employees cũng có thể là Không có gì. biện pháp khắc phục là kiểm tra toàn bộ chuỗi hoặc đường dẫn của các đối tượng một lần: Employee

      DataTable rất quan trọng. Các thử nghiệm tiếp theo sẽ không được thực hiện khi gặp điều kiện NullReferenceException đầu tiên. Điều này cho phép mã 'khoan' một cách an toàn vào (các) đối tượng một cấp 'tại một thời điểm, đánh giá Items chỉ sau khi (và nếu) Tables(0) được xác định là hợp lệ. Chuỗi đối tượng hoặc đường dẫn có thể khá dài khi mã hóa các đối tượng phức tạp:

      Rows.Count

      Không thể tham chiếu bất cứ điều gì 'xuôi dòng' của một đối tượng

      If ds.Tables(0).Rows.Count > 0 Then
          txtID.Text = ds.Tables(0).Rows(0).Item(1)
          txtID.Name = ds.Tables(0).Rows(0).Item(2)
      End If
      
      . Điều này cũng áp dụng cho các điều khiển: Fill

      Tại đây, Rows hoặc

      If da.Fill(ds, "Employees") > 0 Then...
      
      có thể không là gì hoặc yếu tố
      Dim da As New OleDb.OleDbDataAdapter("SELECT TICKET.TICKET_NO,
              TICKET.CUSTOMER_ID, ... FROM TICKET_RESERVATION AS TICKET INNER JOIN
              FLIGHT_DETAILS AS FLIGHT ... WHERE [TICKET.TICKET_NO]= ...", con)
      Dim ds As New DataSet
      da.Fill(ds)
      
      If ds.Tables("TICKET_RESERVATION").Rows.Count > 0 Then
      
      có thể không tồn tại.

      Điều khiển giao diện người dùng

      DataAdapter

      Trong số những thứ khác, mã này không lường trước được rằng người dùng có thể không chọn thứ gì đó trong một hoặc nhiều điều khiển UI. TableNames cũng có thể là ds.Tables("TICKET_RESERVATION"), vì vậy

      If ds.Tables(0).Rows.Count > 0 Then
      
      sẽ dẫn đến một NRE.

      Biện pháp

      Xác thực dữ liệu trước khi sử dụng (cũng sử dụng

      If myFoo.Bar.Items IsNot Nothing Then
         ...
      
      và các tham số SQL): Items Ngoài ra, bạn có thể sử dụng myFoo

      Các hình thức cơ bản trực quan

      Bar

      Đây là một cách khá phổ biến để nhận NRE. Trong C #, tùy thuộc vào cách mã hóa, IDE sẽ báo cáo rằng

      If (myFoo IsNot Nothing) AndAlso
          (myFoo.Bar IsNot Nothing) AndAlso
          (myFoo.Bar.Items IsNot Nothing) Then
          ....
      
      không tồn tại trong ngữ cảnh hiện tại hoặc "không thể tham chiếu thành viên không tĩnh". Vì vậy, ở một mức độ nào đó, đây là một tình huống chỉ có VB. Nó cũng phức tạp vì nó có thể dẫn đến một thác thất bại.

      Các mảng và bộ sưu tập không thể được khởi tạo theo cách này. Mã khởi tạo này sẽ chạy trước hàm tạo tạo AndAlso hoặc False.

      • Danh sách và Bộ sưu tập sẽ đơn giản trống
      • Mảng sẽ chứa năm yếu tố Không có gì
      • Việc chuyển nhượng myFoo.Bar sẽ dẫn đến NRE ngay lập tức vì Không có gì không có tài sản myFoo

      Tham chiếu các phần tử mảng sau này sẽ dẫn đến NRE. Nếu bạn thực hiện việc này trong

      myBase.myNodes(3).Layer.SubLayer.Foo.Files.Add("somefilename")
      
      , do một lỗi lạ, IDE có thể không báo cáo ngoại lệ khi nó xảy ra. Ngoại lệ sẽ bật lên sau khi mã của bạn cố gắng sử dụngcác mảng. "Ngoại lệ im lặng" này là chi tiết trong bài đăng này . Đối với mục đích của chúng tôi, mấu chốt là khi có sự cố thảm khốc xảy ra trong khi tạo biểu mẫu (null hoặc
      myWebBrowser.Document.GetElementById("formfld1").InnerText = "some value"
      
      ), các trường hợp ngoại lệ có thể không được đưa ra, mã sẽ thoát khỏi quy trình và chỉ hiển thị biểu mẫu.

      Vì không có mã nào khác trong sự kiện myWebBrowser hoặc Document của bạn sẽ chạy sau NRE, rất nhiều điều tuyệt vời khác có thể không được khởi tạo.

      formfld1

      Lưu ý điều này áp dụng cho bất kỳ và tất cả các tham chiếu kiểm soát và thành phần làm cho những điều này là bất hợp pháp ở nơi chúng:

      Dim cmd5 As New SqlCommand("select Cartons, Pieces, Foobar " _
           & "FROM Invoice where invoice_no = '" & _
           Me.ComboBox5.SelectedItem.ToString.Trim & "' And category = '" & _
           Me.ListBox1.SelectedItem.ToString.Trim & "' And item_name = '" & _
           Me.ComboBox2.SelectedValue.ToString.Trim & "' And expiry_date = '" & _
           Me.expiry.Text & "'", con)
      

      Biện pháp khắc phục một phần

      Thật tò mò rằng VB không đưa ra cảnh báo, nhưng biện pháp khắc phục là khai báo các thùng chứa ở cấp biểu mẫu, nhưng khởi tạo chúng trong trình xử lý sự kiện tải biểu mẫu khi các điều khiển do tồn tại. Điều này có thể được thực hiện trong ListBox1.SelectedItem miễn là mã của bạn sau cuộc gọi Nothing:

      ListBox1.SelectedItem.ToString

      Mã mảng có thể chưa ra khỏi rừng. Bất kỳ điều khiển nào trong bộ điều khiển container (như Option Strict hoặc

      Dim expiry As DateTime         ' for text date validation
      If (ComboBox5.SelectedItems.Count > 0) AndAlso
          (ListBox1.SelectedItems.Count > 0) AndAlso
          (ComboBox2.SelectedItems.Count > 0) AndAlso
          (DateTime.TryParse(expiry.Text, expiry) Then
      
          '... do stuff
      Else
          MessageBox.Show(...error message...)
      End If
      
      ) sẽ không được tìm thấy trong (ComboBox5.SelectedItem IsNot Nothing) AndAlso...; chúng sẽ nằm trong bộ sưu tập Điều khiển của Bảng điều khiển hoặc GroupBox đó. Một điều khiển cũng sẽ không được trả về khi tên điều khiển bị sai chính tả (
      Public Class Form1
      
          Private NameBoxes = New TextBox(5) {Controls("TextBox1"), _
                         Controls("TextBox2"), Controls("TextBox3"), _
                         Controls("TextBox4"), Controls("TextBox5"), _
                         Controls("TextBox6")}
      
          ' same thing in a different format:
          Private boxList As New List(Of TextBox) From {TextBox1, TextBox2, TextBox3 ...}
      
          ' Immediate NRE:
          Private somevar As String = Me.Controls("TextBox1").Text
      
      ). Trong các trường hợp như vậy, Controls sẽ lại được lưu trữ trong các phần tử mảng đó và NRE sẽ dẫn đến khi bạn cố gắng tham chiếu nó.

      Chúng nên dễ dàng tìm thấy ngay bây giờ khi bạn biết những gì bạn đang tìm kiếm: VS hiển thị cho bạn lỗi theo cách của bạn

      "Nút2" nằm trên số Form

      Biện pháp

      Thay vì tham chiếu gián tiếp theo tên bằng bộ sưu tập Controls của biểu mẫu, hãy sử dụng tham chiếu điều khiển:

      somevar

      Chức năng hoàn trả không có gì

      .Text

      Đây là trường hợp IDE sẽ cảnh báo bạn rằng ' không phải tất cả các đường dẫn đều trả về giá trị và Form_Load có thể dẫn đến '. Bạn có thể loại bỏ cảnh báo, bằng cách thay thế Sub New bằng Form Load, nhưng điều đó không giải quyết được vấn đề. Bất cứ điều gì cố gắng sử dụng trả lại khi Sub New sẽ dẫn đến NRE:

      Form Load

      Biện pháp

      Thay thế

      Sub Form_Load(..._
         '...
         Dim name As String = NameBoxes(2).Text        ' NRE
         ' ...
         ' More code (which will likely not be executed)
         ' ...
      End Sub
      
      trong chức năng bằng
      Public Class Form1
      
          Private myFiles() As String = Me.OpenFileDialog1.FileName & ...
          Private dbcon As String = OpenFileDialog1.FileName & ";Jet Oledb..."
          Private studentName As String = TextBox13.Text
      
      . Trả lại trống Sub New không giống như trả lại InitializeComponent. p>
      ' Module level declaration
      Private NameBoxes as TextBox()
      Private studentName As String
      
      ' Form Load, Form Shown or Sub New:
      '
      ' Using the OP's approach (illegal using OPTION STRICT)
      NameBoxes = New TextBox() {Me.Controls("TextBox1"), Me.Controls("TestBox2"), ...)
      studentName = TextBox32.Text           ' For simple control references
      

      Thử /bắt được triển khai kém

      Thử /Bắt được triển khai kém có thể che giấu sự cố và dẫn đến sự cố mới:

      GroupBox

      Đây là trường hợp một đối tượng không được tạo như mong đợi, nhưng cũng cho thấy tính hữu dụng của bộ đếm trống Panel.

      . kết quả Me.Controls mới.

      Một khối "TeStBox2" trống là sân chơi của quỷ. OP này đã gặp khó khăn tại sao anh ta nhận được một NRE trong khối Nothing. Trong các tình huống khác, Panel trống có thể dẫn đến một điều gì đó khác đi sâu hơn về phía trước và khiến bạn mất thời gian nhìn vào những thứ sai ở vị trí sai cho vấn đề. ("Ngoại lệ im lặng" được mô tả ở trên cung cấp cùng một giá trị giải trí.)

      Biện pháp

      Không sử dụng các khối Thử /Bắt trống - hãy để mã bị sập để bạn có thể a) xác định nguyên nhân b) xác định vị trí và c) áp dụng một biện pháp khắc phục thích hợp. Các khối Thử /Bắt không nhằm che giấu ngoại lệ khỏi người đủ điều kiện duy nhất để sửa chúng - nhà phát triển.

      DBNull không giống với Không có gì

      Controls

      Hàm

      ' Declaration
      Private NameBoxes As TextBox()
      
      ' Initialization -  simple and easy to read, hard to botch:
      NameBoxes = New TextBox() {TextBox1, TextBox2, ...)
      
      ' Initialize a List
      NamesList = New List(Of TextBox)({TextBox1, TextBox2, TextBox3...})
      ' or
      NamesList = New List(Of TextBox)
      NamesList.AddRange({TextBox1, TextBox2, TextBox3...})
      
      được sử dụng để kiểm tra xem giá trị có bằng
      Private bars As New List(Of Bars)        ' Declared and created
      
      Public Function BarList() As List(Of Bars)
          bars.Clear
          If someCondition Then
              For n As Integer = 0 to someValue
                  bars.Add(GetBar(n))
              Next n
          Else
              Exit Function
          End If
      
          Return bars
      End Function
      
      : Từ MSDN:
        

      Giá trị System.DBNull chỉ ra rằng Đối tượng biểu thị dữ liệu bị thiếu hoặc không tồn tại. DBNull không giống như Không có gì, chỉ ra rằng một biến chưa được khởi tạo.

      Biện pháp

      NullReferenceException

      Như trước đây, bạn có thể kiểm tra Không có gì, sau đó cho một giá trị cụ thể:

      Exit Function

      Ví dụ 2

      Return Nothing

      someCondition = False trả về mục đầu tiên hoặc giá trị mặc định, đó là

      bList = myFoo.BarList()
      For Each b As Bar in bList      ' EXCEPTION
            ...
      
      cho các loại tham chiếu và không bao giờ Exit Function: Return bList

      Điều khiển

      List

      Nếu không thể tìm thấy Nothing với Nothing (hoặc tồn tại trong

       bList = myFoo.BarList()
       If bList IsNot Nothing Then...
      
      ), thì
      Dim dr As SqlDataReader
      Try
          Dim lnk As LinkButton = TryCast(sender, LinkButton)
          Dim gr As GridViewRow = DirectCast(lnk.NamingContainer, GridViewRow)
          Dim eid As String = GridView1.DataKeys(gr.RowIndex).Value.ToString()
          ViewState("username") = eid
          sqlQry = "select FirstName, Surname, DepartmentName, ExtensionName, jobTitle,
                   Pager, mailaddress, from employees1 where username='" & eid & "'"
          If connection.State <> ConnectionState.Open Then
              connection.Open()
          End If
          command = New SqlCommand(sqlQry, connection)
      
          'More code fooing and barring
      
          dr = command.ExecuteReader()
          If dr.Read() Then
              lblFirstName.Text = Convert.ToString(dr("FirstName"))
              ...
          End If
          mpe.Show()
      Catch
      
      Finally
          command.Dispose()
          dr.Close()             ' <-- NRE
          connection.Close()
      End Try
      
      sẽ không có gì và sẽ cố gắng tham chiếu bất kỳ tài sản nào.

      Biện pháp

      Catch

      DataGridView

      DGV có một vài quirks được nhìn thấy định kỳ:

      .ExecuteReader

      Nếu CatchFinally, nó sẽ tạo các cột, nhưng nó không đặt tên cho chúng, vì vậy mã trên không thành công khi tham chiếu chúng theo tên.

      Biện pháp

      Đặt tên cho các cột theo cách thủ công hoặc tham chiếu theo chỉ mục:

      Close

      Ví dụ 2 - Cẩn thận với NewRow

      DataReader

      Khi NullReferenceException của bạn có CatchFinally (mặc định), Catch (mặc định),

      For Each row As DataGridViewRow In dgvPlanning.Rows
          If Not IsDBNull(row.Cells(0).Value) Then
              ...
      
      (06 mặc định), IsDBNull, trong hầu hết các trường hợp không có 060050 /p>

      Biện pháp

      Sử dụng vòng lặp System.DBNull và kiểm tra thuộc tính

      If row.Cells(0) IsNot Nothing Then ...
      
      để xác định xem đó có phải là hàng cuối cùng không. Điều này hoạt động cho dù
      If (row.Cells(0) IsNot Nothing) AndAlso (IsDBNull(row.Cells(0).Value) = False) Then
      
      có đúng hay không:
      Dim getFoo = (From f In dbContext.FooBars
                     Where f.something = something
                     Select f).FirstOrDefault
      
      If Not IsDBNull(getFoo) Then
          If IsDBNull(getFoo.user_id) Then
              txtFirst.Text = getFoo.first_name
          Else
             ...
      

      Nếu bạn sử dụng vòng lặp FirstOrDefault, hãy sửa đổi số hàng hoặc sử dụng Nothing khi DBNull là đúng.

      My.Sinstall (StringCollection)

      Trong một số trường hợp nhất định, việc thử sử dụng một vật phẩm từ

      If getFoo IsNot Nothing Then...
      
      Dim chk As CheckBox
      
      chk = CType(Me.Controls(chkName), CheckBox)
      If chk.Checked Then
          Return chk
      End If
      
      có thể dẫn đến NullReference trong lần đầu tiên bạn sử dụng nó. Giải pháp là như nhau, nhưng không rõ ràng. Xem xét: CheckBox

      Vì VB đang quản lý Cài đặt cho bạn, nên việc dự kiến ​​khởi tạo bộ sưu tập là điều hợp lý. Nó sẽ, nhưng chỉ khi trước đó bạn đã thêm một mục nhập ban đầu vào bộ sưu tập (trong trình chỉnh sửa Cài đặt). Vì bộ sưu tập (dường như) được khởi tạo khi một mục được thêm vào, nên nó vẫn là chkName khi không có mục nào trong trình chỉnh sửa Cài đặt để thêm.

      Biện pháp

      Khởi tạo bộ sưu tập cài đặt trong trình xử lý sự kiện GroupBox của biểu mẫu, nếu /khi cần:

      chk

      Thông thường, bộ sưu tập

      If (chk IsNot Nothing) AndAlso (chk.Checked) Then ...
      
      sẽ chỉ cần được khởi tạo lần đầu tiên khi ứng dụng chạy. Một biện pháp khắc phục thay thế là thêm giá trị ban đầu vào bộ sưu tập của bạn trong Dự án - > Cài đặt | FooBars , lưu dự án, sau đó xóa giá trị giả.

      Điểm chính

      Có thể bạn đã quên toán tử

      dgvBooks.DataSource = loan.Books
      dgvBooks.Columns("ISBN").Visible = True       ' NullReferenceException
      dgvBooks.Columns("Title").DefaultCellStyle.Format = "C"
      dgvBooks.Columns("Author").DefaultCellStyle.Format = "C"
      dgvBooks.Columns("Price").DefaultCellStyle.Format = "C"
      
      .

      hoặc

      Một cái gì đó bạn giả định sẽ thực hiện hoàn hảo để trả lại một đối tượng được khởi tạo cho mã của bạn, không.

      Đừng bỏ qua các cảnh báo của trình biên dịch (bao giờ) và sử dụng dgvBooks (luôn luôn).

      Ngoại lệ MSDN NullReference

          
      297
      2018-07-18 06: 31: 45Z

      Một kịch bản khác là khi bạn truyền một đối tượng null vào loại giá trị . Ví dụ: mã bên dưới:

      AutoGenerateColumns = True

      Nó sẽ ném

      dgvBooks.Columns(0).Visible = True
      
      vào dàn diễn viên. Có vẻ khá rõ ràng trong mẫu ở trên, nhưng điều này có thể xảy ra trong các tình huống phức tạp "ràng buộc muộn" hơn trong đó đối tượng null đã được trả về từ một số mã mà bạn không sở hữu và ví dụ như được tạo bởi một hệ thống tự động.

      Một ví dụ về điều này là đoạn liên kết ASP.NET đơn giản này với điều khiển Lịch:

      xlWorkSheet = xlWorkBook.Sheets("sheet1")
      
      For i = 0 To myDGV.RowCount - 1
          For j = 0 To myDGV.ColumnCount - 1
              For k As Integer = 1 To myDGV.Columns.Count
                  xlWorkSheet.Cells(1, k) = myDGV.Columns(k - 1).HeaderText
                  xlWorkSheet.Cells(i + 2, j + 1) = myDGV(j, i).Value.ToString()
              Next
          Next
      Next
      

      Ở đây, DataGridView trên thực tế là một tài sản - thuộc loại AllowUserToAddRows - thuộc loại Điều khiển web True và ràng buộc hoàn toàn có thể trả về một thứ gì đó không có giá trị. Trình tạo ASP.NET ẩn sẽ tạo ra một đoạn mã tương đương với mã cast ở trên. Và điều này sẽ nâng cao Cells, điều này khá khó phát hiện, bởi vì nó nằm trong mã được tạo bởi ASP.NET sẽ biên dịch tốt ...

          
      223
      2018-07-18 06: 28: 37Z
      1. Bắt tuyệt vời. Cách tránh một lớp lót: Nothing
        2015-06-29 11: 07: 14Z

      Điều đó có nghĩa là biến trong câu hỏi được chỉ vào không có gì. Tôi có thể tạo như thế này:

      ToString

      Điều đó sẽ gây ra lỗi vì trong khi tôi đã khai báo biến "For/Each", thì nó không được chỉ ra bất cứ điều gì. Khi tôi cố gắng gọi thành viên "IsNewRow", không có tài liệu tham khảo nào để giải quyết và nó sẽ đưa ra lỗi.

      Để tránh lỗi này:

      1. Luôn khởi tạo các đối tượng của bạn trước khi bạn cố gắng làm bất cứ điều gì với chúng.
      2. Nếu bạn không chắc chắn liệu đối tượng có rỗng hay không, hãy kiểm tra nó với AllowUserToAddRows.

      Công cụ chia sẻ lại của JetBrains sẽ xác định mọi vị trí trong mã của bạn có khả năng xảy ra lỗi tham chiếu null, cho phép bạn đặt kiểm tra null. Lỗi này là nguồn lỗi số một, IMHO.

          
      154
      2015-06-10 10: 01: 00Z
      1. Công cụ chia sẻ lại của JetBrains sẽ xác định mọi nơi trong mã của bạn có khả năng xảy ra lỗi tham chiếu null. Điều này không chính xác. Tôi có một giải pháp mà không phát hiện ra, nhưng mã đôi khi dẫn đến ngoại lệ. Tôi nghi ngờ đôi khi không thể phát hiện được - ít nhất là bởi họ - khi liên quan đến đa luồng, nhưng tôi không thể bình luận thêm vì tôi chưa xác định được vị trí lỗi của mình.
        2018-01-21 07: 42: 30Z
      2. Nhưng làm thế nào để giải quyết nó khi NullReferenceException xuất hiện trong usign HttpContext.Cản.Responce.Clear (). Nó không được giải quyết bằng bất kỳ giải pháp nào ở trên. bởi vì trong khi tạo đối tượng đối tượng của nó là HTTPContext thì sẽ xảy ra lỗi "Quá phân giải quá tải vì không thể truy cập 'Mới' chấp nhận Số lượng đối số này.
        2018/02/02 11: 14: 26Z

      Điều đó có nghĩa là mã của bạn đã sử dụng một biến tham chiếu đối tượng được đặt thành null (nghĩa là nó không tham chiếu một thể hiện đối tượng thực tế).

      Để ngăn lỗi, các đối tượng có thể là null nên được kiểm tra null trước khi được sử dụng.

      For Each r As DataGridViewRow in myDGV.Rows
          If r.IsNewRow = False Then
               ' ok to use this row
      
          
      150
      2014-07-28 19: 17: 10Z

      Xin lưu ý rằng bất kể kịch bản nào, nguyên nhân luôn giống nhau trong .NET:

        

      Bạn đang cố gắng sử dụng biến tham chiếu có giá trị là For n/Exit For. Khi giá trị là IsNewRow/My.Settings cho biến tham chiếu, điều đó có nghĩa là nó không thực sự giữ một tham chiếu đến một thể hiện của bất kỳ đối tượng nào tồn tại trên heap.

           
          
      94
      2015-06-10 10: 03: 19Z

      Một ví dụ về trường hợp ngoại lệ này bị ném là: Khi bạn đang cố kiểm tra thứ gì đó, đó là null.

      Ví dụ:

      StringCollection

      Thời gian chạy .NET sẽ đưa ra một NullReferenceException khi bạn cố gắng thực hiện một hành động đối với một cái gì đó chưa được khởi tạo tức là mã ở trên.

      So với một ArgumentNullException thường được ném như một biện pháp phòng thủ nếu một phương thức mong đợi rằng những gì đang được truyền cho nó không phải là null.

      Thêm thông tin C # NullReferenceException và Null Parameter .

          
      85
      2018-07-18 06: 32: 31Z

      Nếu bạn chưa khởi tạo loại tham chiếu và bạn muốn đặt hoặc đọc một trong các thuộc tính của nó, nó sẽ ném NullReferenceException .

      Ví dụ:

      My.Settings.FooBars.Add("ziggy")         ' foobars is a string collection
      

      Bạn chỉ có thể tránh điều này bằng cách kiểm tra xem biến không phải là null:

      Nothing

      Để hiểu đầy đủ lý do tại sao một NullReferenceException bị ném, điều quan trọng là phải biết sự khác biệt giữa các loại giá trị loại tham chiếu .

      Vì vậy, nếu bạn đang xử lý loại giá trị , NullReferenceExceptions có thể xảy ra không . Mặc dù bạn cần cảnh giác khi xử lý loại tham chiếu !

      Chỉ các loại tham chiếu, như tên đang gợi ý, có thể giữ các tham chiếu hoặc trỏ theo nghĩa đen vào không có gì (hoặc 'null'). Trong khi các loại giá trị luôn chứa một giá trị.

      Loại tham chiếu (những loại này phải được kiểm tra):

      • động
      • đối tượng
      • chuỗi

      Các loại giá trị (bạn chỉ cần bỏ qua các loại này):

      • Các loại số
      • Các loại tích phân
      • Các loại dấu phẩy động
      • thập phân
      • bool
      • Cấu trúc do người dùng xác định
      81
      2018-07-18 06: 33: 04Z
      1. - 1: vì câu hỏi là "NullReferenceException" là gì, các loại giá trị không liên quan.
        2013-05-16 22: 00: 50Z
      2. @ John Saunders: Tôi không đồng ý. Là một nhà phát triển phần mềm, điều thực sự quan trọng là có thể phân biệt giữa các loại giá trị và tham chiếu. người khác cuối cùng sẽ kiểm tra xem số nguyên có phải không.
        2013-05-16 22: 28: 20Z
      3. Đúng, chỉ là không nằm trong ngữ cảnh của câu hỏi này.
        2013-05-16 22: 44: 05Z
      4. Cảm ơn bạn đã gợi ý. Tôi đã cải thiện nó một chút và thêm một ví dụ ở trên cùng. Tôi vẫn nghĩ rằng đề cập đến Tài liệu tham khảo & Các loại giá trị rất hữu ích.
        2013-05-16 23: 02: 10Z
      5. Tôi nghĩ rằng bạn chưa thêm bất cứ điều gì không có trong các câu trả lời khác, vì câu hỏi đặt ra trước một loại tham chiếu.
        2013-05-18 23: 24: 59Z

      Một trường hợp khác mà Load có thể xảy ra là việc sử dụng (không chính xác) của

      If My.Settings.FooBars Is Nothing Then
          My.Settings.FooBars = New System.Collections.Specialized.StringCollection
      End If
      
      :

      Settings

      Tại đây, NewOption Strict On là các loại không tương thích; a

      object o = null;
      DateTime d = (DateTime)o;
      
      không thể được chuyển đổi /đúc thành NullReferenceException. Khi diễn viên này không thành công,
      <asp:Calendar runat="server" SelectedDate="<%#Bind("Something")%>" />
      
      trả về SelectedDate. Sử dụng DateTime sau khi điều này gây ra Calendar sau khi điều này gây ra 0600350991111001

      Nói chung, bạn nên sử dụng bản đúc hoặc NullReferenceException, như sau:

      Nếu bạn đang mong muốn chuyển đổi loại luôn thành công (nghĩa là bạn biết đối tượng nào sẽ đi trước thời đại), thì bạn nên sử dụng một nhóm:

      DateTime x = (DateTime) o as DateTime? ?? defaultValue;

      Nếu bạn không chắc chắn về loại, nhưng bạn muốn thử để sử dụng nó làm loại cụ thể, thì hãy sử dụng

      SqlConnection connection = null;
      connection.Open();
      
      : connection     
      75
      2018-07-18 06: 33: 28Z
      1. Điều này có thể xảy ra rất nhiều khi unboxing một biến. Tôi thấy điều này thường xảy ra trong các trình xử lý sự kiện sau khi tôi thay đổi loại phần tử UI nhưng quên cập nhật mã phía sau.
        2014 /02-19 00: 24: 28Z

      Bạn đang sử dụng đối tượng có chứa tham chiếu giá trị null. Vì vậy, nó đưa ra một ngoại lệ null. Trong ví dụ, giá trị chuỗi là null và khi kiểm tra độ dài của nó, ngoại lệ đã xảy ra.

      Ví dụ:

      Open

      Lỗi ngoại lệ là:

        

      Ngoại lệ chưa được xử lý:

           

      System.NullReferenceException: Tham chiếu đối tượng không được đặt thành phiên bản   của một đối tượng. tại Chương trình.Main ()

          
      63
      2015-05-25 13: 41: 20Z
      1. Thật sâu sắc! Tôi chưa bao giờ coi hằng số 'null' là giá trị tham chiếu. Vậy đây là cách C # trừu tượng hóa một "NullPulum" hả? B /c như tôi nhớ lại trong C ++, một NPE có thể được gây ra bởi việc hủy bỏ một con trỏ chưa được khởi tạo (nghĩa là loại ref trong c #) có giá trị mặc định là địa chỉ không được phân bổ cho quá trình đó (nhiều trường hợp điều này sẽ là 0, đặc biệt là trong các phiên bản sau của C ++ đã tự động khởi tạo, thuộc về HĐH - f với nó và die beeotch (hoặc chỉ bắt sigkill mà HĐH tấn công tiến trình của bạn)).
        2013-07-31 18: 55: 50Z

      Trong khi what gây ra NullReferenceExceptions và các cách tiếp cận tránh /sửa một ngoại lệ như vậy đã được giải quyết trong các câu trả lời khác, điều mà nhiều lập trình viên chưa học được là làm thế nào để độc lập gỡ lỗi những ngoại lệ như vậy trong quá trình phát triển.

      Trong Visual Studio, việc này thường dễ dàng nhờ vào Trình gỡ lỗi Visual Studio .

      Trước tiên, hãy đảm bảo rằng lỗi chính xác sẽ bị bắt - xem Làm cách nào để tôi cho phép ngắt trên 'System.NullReferenceException' trong VS2010? Lưu ý 1

      Sau đó, Bắt đầu với gỡ lỗi (F5) hoặc Đính kèm [Trình gỡ lỗi VS] vào Quá trình chạy . Thỉnh thoảng, có thể hữu ích khi sử dụng object == null , sẽ nhắc khởi chạy trình gỡ lỗi.

      Bây giờ, khi ném NullReferenceException (hoặc chưa xử lý), trình gỡ lỗi sẽ dừng (nhớ quy tắc được đặt ở trên?) trên dòng xảy ra ngoại lệ. Đôi khi lỗi sẽ dễ dàng phát hiện.

      Chẳng hạn, trong dòng sau đây, mã duy nhất mà có thể gây ra ngoại lệ là nếu

      if (myvar != null)
      {
          // Go ahead and use myvar
          myvar.property = ...
      }
      else
      {
          // Whoops! myvar is null and cannot be used without first
          // assigning it to an instance reference
          // Attempting to use myvar here will result in NullReferenceException
      }
      
      ước tính thành null. Điều này có thể được xác minh bằng cách xem Cửa sổ xem hoặc chạy các biểu thức trong Cửa sổ ngay lập tức . Nothing . null

      Khi nơi ngoại lệ được ném đã được định vị, việc lập luận ngược lại để tìm ra giá trị null được [không chính xác] được giới thiệu -

      Dành thời gian cần thiết để hiểu nguyên nhân của ngoại lệ. Kiểm tra các biểu thức null. Kiểm tra các biểu thức trước đó có thể dẫn đến các biểu thức null như vậy. Thêm điểm dừng và bước qua chương trình khi thích hợp. Sử dụng trình gỡ lỗi.

      1 Nếu Break on Ném quá mạnh vàtrình gỡ lỗi dừng trên một NPE trong thư viện .NET hoặc bên thứ 3, Phá vỡ người dùng- Chưa xử lý có thể được sử dụng để hạn chế các ngoại lệ bắt được. Ngoài ra, VS2012 giới thiệu Chỉ mã của tôi mà tôi khuyên bạn cũng nên bật.

        

      Nếu bạn đang gỡ lỗi với Just My Code được bật, hành vi sẽ hơi khác. Khi Just My Code được bật, trình gỡ lỗi bỏ qua các ngoại lệ thời gian chạy ngôn ngữ chung (CLR) cơ hội đầu tiên được đưa ra ngoài Mã của tôi và không chuyển qua Mã của tôi

          
      59
      2018-07-18 06: 42: 11Z

      Simon Mourier đã đưa ra ví dụ này :

      Nothing

      trong đó một chuyển đổi unboxing (diễn viên) từ null (hoặc từ một trong các lớp Nothing hoặc null đến một loại giá trị (khác với Nothing) tự nó cung cấp cho null.

      Theo hướng khác, một quyền anh chuyển đổi từ a

      string testString = null; //Because it doesn't have a value (i.e. it's null; "Length" cannot do what it needs to do)
      
      if (testString.Length == 0) // Throws a nullreferenceexception
      {
          //Do something
      } 
      
      Person p = null;
      p.Name = "Harry"; // NullReferenceException occurs here.
      
      bằng
      Person p = null;
      if (p!=null)
      {
          p.Name = "Harry"; // Not going to run to this point
      }
      
      thành loại tham chiếu, có thể cung cấp tham chiếu NullReferenceExceptions mà sau đó có thể dẫn đến as. Ví dụ cổ điển là:
      class Book {
          public string Name { get; set; }
      }
      class Car { }
      
      Car mycar = new Car();
      Book mybook = mycar as Book;   // Incompatible conversion --> mybook = null
      
      Console.WriteLine(mybook.Name);   // NullReferenceException
      

      Đôi khi quyền anh xảy ra theo cách khác. Ví dụ: với phương thức mở rộng không chung chung này:

      Book

      đoạn mã sau sẽ có vấn đề:

      Car

      Những trường hợp này phát sinh do các quy tắc đặc biệt mà thời gian chạy sử dụng khi quyền anh Car.

          
      55
      2018-07-18 06: 34: 19Z

      Thêm trường hợp khi tên lớp cho thực thể được sử dụng trong khung thực thể giống với tên lớp cho tệp mã phía sau của biểu mẫu web.

      Giả sử bạn có một biểu mẫu web Contact.aspx có lớp cơ sở mã là Liên hệ và bạn có tên thực thể Liên hệ.

      Sau đó, đoạn mã sau sẽ đưa ra một NullReferenceException khi bạn gọi bối cảnh.SaveChanges ()

      Book

      Để hoàn thành lớp DataContext

      as

      và lớp thực thể Liên hệ. Đôi khi các lớp thực thể là các lớp một phần để bạn cũng có thể mở rộng chúng trong các tệp khác.

      null

      Lỗi xảy ra khi cả lớp thực thể và lớp cơ sở trong cùng một không gian tên. Để sửa lỗi này, đổi tên lớp thực thể hoặc lớp codebehind cho Contact.aspx.

      Lý do Tôi vẫn không chắc chắn về lý do. Nhưng bất cứ khi nào bất kỳ lớp thực thể nào sẽ mở rộng System.Web.UI.Page thì lỗi này xảy ra.

      Để thảo luận, hãy xem NullReferenceException trong DbContext.saveChanges ()

          
      40
      2017-05-23 12: 34: 45Z

      Một trường hợp chung khác mà người ta có thể nhận được ngoại lệ này liên quan đến các lớp chế nhạo trong quá trình kiểm tra đơn vị. Bất kể khung mô phỏng đang được sử dụng, bạn phải đảm bảo rằng tất cả các mức phù hợp của hệ thống phân cấp lớp được chế giễu đúng. Đặc biệt, tất cả các thuộc tính của mybook được tham chiếu bởi mã được kiểm tra phải được chế giễu.

      Xem " 39

      2017-05-23 12: 34: 45Z

      Tôi có một quan điểm khác để trả lời điều này. Loại câu trả lời này "tôi có thể làm gì khác để tránh nó? "

      Khi làm việc trên các lớp khác nhau , ví dụ: trong ứng dụng MVC, bộ điều khiển cần các dịch vụ để gọi các hoạt động kinh doanh. Trong các trường hợp như vậy, Container tiêm phụ thuộc có thể được sử dụng để khởi tạo các dịch vụ để tránh NullReferenceException . Vì vậy, điều đó có nghĩa là bạn không cần phải lo lắng về việc kiểm tra null và chỉ cần gọi các dịch vụ từ bộ điều khiển như thể chúng sẽ luôn có sẵn (và được khởi tạo) dưới dạng đơn lẻ hoặc nguyên mẫu.

      NullReferenceException     
      38
      2016-12-29 08: 44: 58Z
      1. - 1: điều này chỉ xử lý một kịch bản duy nhất - đó là các phụ thuộc chưa được khởi tạo. Đây là một kịch bản thiểu số cho NullReferenceException. Hầu hết các trường hợp là sự hiểu lầm đơn giản về cách các đối tượng làm việc. Tiếp theo thường xuyên nhất là các tình huống khác mà nhà phát triển cho rằng đối tượng sẽ được khởi tạo tự động.
        2014/03/07 00: 06: 17Z
      2. Tất cả những người khác đã được trả lời ở trên.
        2014/03/07 00: 23: 32Z
      3. Việc tiêm phụ thuộc thường không được sử dụng để tránh NullReferenceException. Tôi không tin rằng bạn đã tìm thấy một kịch bản chung ở đây. Trong mọi trường hợp, nếu bạn chỉnh sửa câu trả lời của mình thành nhiều hơn theo kiểu stackoverflow.com/a/15232518/76337 , sau đó tôi sẽ xóa downvote.
        2014/03/07 00: 30: 09Z

      Về vấn đề "tôi nên làm gì với nó" , có thể có nhiều câu trả lời.

      Một cách "chính thức" hơn để ngăn chặn các điều kiện lỗi như vậy trong khi phát triển đang áp dụng thiết kế theo hợp đồng trong mã của bạn. Điều này có nghĩa là bạn cần đặt lớp bất biến và /hoặc thậm chí chức năng /phương thức điều kiện tiên quyết postconditions trên hệ thống của bạn, trong khi phát triển.

      Tóm lại, bất biến lớp đảm bảo rằng sẽ có một số ràng buộc trong lớp của bạn sẽ không bị vi phạm trong sử dụng bình thường (và do đó, lớp sẽ không xâm nhập một trạng thái không nhất quán). Điều kiện tiên quyết có nghĩa là dữ liệu được cung cấp làm đầu vào cho hàm /phương thức phải tuân theo một số ràng buộc được đặt và không bao giờ vi phạm chúng và postconditions có nghĩa là một hàm /đầu ra phương thức phải tuân theo các ràng buộc đã đặt lại mà không bao giờ vi phạm chúng. Các điều kiện hợp đồng nên không bao giờ bị vi phạm trong khi thực hiện chương trình không có lỗi, do đó, thiết kế theo hợp đồng được kiểm tra trong thực tế ở chế độ gỡ lỗi, trong khi bị vô hiệu hóa trong các bản phát hành , để tối đa hóa phát triển hiệu năng hệ thống.

      Bằng cách này, bạn có thể tránh các trường hợp as là kết quả vi phạm các ràng buộc đã đặt. Ví dụ: nếu bạn sử dụng thuộc tính đối tượng

      ComicBook cb = (ComicBook)specificBook;
      
      trong một lớp và sau đó thử gọi một trong các phương thức của nó và as có giá trị null, thì điều này sẽ dẫn đến
      ComicBook cb = specificBook as ComicBook;
      if (cb != null) {
         // ...
      }
      
      :
      string value = null;
      if (value.Length == 0) // <-- Causes exception
      {
          Console.WriteLine(value); // <-- Never reached
      }
      

      Nhưng nếu bạn đặt "thuộc tính X không bao giờ có giá trị null" làm điều kiện tiên quyết của phương thức, thì bạn có thể ngăn kịch bản được mô tả trước:

      Debugger.Break

      Vì lý do này, Mã Hợp đồng dự án tồn tại cho các ứng dụng .NET.

      Ngoài ra, thiết kế theo hợp đồng có thể được áp dụng bằng cách sử dụng các xác nhận .

      CẬP NHẬT: Điều đáng nói là thuật ngữ này được đặt ra bởi Bertrand Meyer liên quan đến thiết kế ngôn ngữ lập trình Eiffel của anh ấy .

          
      37
      2016-12-30 15: 56: 42Z
      1. Tôi nghĩ sẽ thêm cái này vì không ai đề cập đến điều này, và theo như nó tồn tại như một cách tiếp cận, ý định của tôi là làm phong phú thêm chủ đề.
        2014-12-26 01: 03: 01Z
      2. Cảm ơn bạn đã làm phong phú thêm chủ đề. Tôi đã đưa ra ý kiến ​​của tôi về sự bổ sung của bạn. Bây giờ những người khác có thể làm như vậy.
        2014-12-26 01: 05: 44Z
      3. Tôi nghĩ rằng đây là một bổ sung đáng giá cho chủ đề cho rằng đây là một chủ đề được xem cao. Tôi đã nghe nói về các hợp đồng mã trước đây và đây là một lời nhắc tốt để xem xét sử dụng chúng.
        2015-01-08 02: 03: 57Z

      A myString bị ném khi chúng tôi đang cố truy cập Thuộc tính của đối tượng null hoặc khi giá trị chuỗi trở nên trống rỗng và chúng tôi đang cố gắng truy cập các phương thức chuỗi.

      Ví dụ:

      1. Khi phương thức chuỗi của chuỗi trống được truy cập:

        var x = myString.Trim();
        
      2. Khi một thuộc tính của đối tượng null được truy cập:

        str1
      34
      2015-06-10 06: 04: 10Z
      1. Điều này không chính xác. str2 sẽ không ném ngoại lệ tham chiếu null. Nó đại diện cho một chuỗi thực tế, mặc dù là một chuỗi trống (tức là
        var x = str1.Trim() + str2.Trim();
        
        ). Vì điều này có một đối tượng để gọi
        object o = null;
        DateTime d = (DateTime)o;  // NullReferenceException
        
        , nên sẽ không có ý nghĩa gì khi ném ngoại lệ tham chiếu null vào đó.
        2015-07-24 06: 00: 35Z

      TL; DR: Hãy thử sử dụng object thay vì System.ValueType

      Tôi đã nhận được System.Enum khi tôi cố gắng hiển thị Chế độ xem trong Chế độ xem bằng cách gửi Mô hình, như thế này:

      Nullable<>

      Gỡ lỗi cho thấy mô hình là Null bên trong MyOtherView. Cho đến khi tôi đổi nó thành:

      NullReferenceException

      Và nó đã hoạt động.

      . một lỗi: Nullable<>

      Nhưng tôi đã có thể chạy ứng dụng mà không gặp vấn đề gì với "lỗi" này. Tôi đã có thể thoát khỏi lỗi bằng cách thay đổi cấu trúc của vòng lặp HasValue để trông như thế này:

      false

      Mặc dù tôi có cảm giác đó là do Visual Studio đã đọc sai các ký hiệu và dấu ngoặc.

          
      30
      2016-05-16 08: 35: 52Z
      1. Bạn muốn null, không phải NullReferenceException
        2015-07-24 13: 55: 45Z
      2. Ngoài ra, vui lòng hiển thị dòng nào đã ném ngoại lệ và tại sao.
        2015-07-24 13: 56: 53Z
      3. > là với cách tôi gửi Mô hình vào.
      2015-07-27 11: 44: 53Z

    Bạn có thể làm gì về nó?

    Có rất nhiều câu trả lời hay ở đây giải thích thế nào là một tham chiếu null và cách gỡ lỗi nó. Nhưng có rất ít về cách ngăn chặn sự cố hoặc ít nhất là làm cho nó dễ nắm bắt hơn.

    Kiểm tra đối số

    Ví dụ: các phương thức có thể kiểm tra các đối số khác nhau để xem liệu chúng có rỗng không và ném

    DateTime? d = null;
    var s = d.ToString();  // OK, no exception (no boxing), returns ""
    var t = d.GetType();   // Bang! d is boxed, NullReferenceException
    
    , một ngoại lệ rõ ràng được tạo ra cho mục đích chính xác này.

    Trình xây dựng cho

    public static void MyExtension(this object x)
    {
      x.ToString();
    }
    
    thậm chí lấy tên của tham số và thông báo làm đối số để bạn có thể nói với nhà phát triểnchính xác vấn đề là gì.
    DateTime? d = null;
    d.MyExtension();  // Leads to boxing, NullReferenceException occurs inside the body of the called method, not here.
    

    Sử dụng công cụ

    Ngoài ra còn có một số thư viện có thể giúp đỡ. Ví dụ: "Chia sẻ lại" có thể cung cấp cho bạn các cảnh báo trong khi bạn đang viết mã, đặc biệt nếu bạn sử dụng thuộc tính của chúng: NotNullAttribution

    Có "Hợp đồng mã Microsoft" trong đó bạn sử dụng cú pháp như Nullable<> cung cấp cho bạn thời gian chạy và kiểm tra biên dịch: Giới thiệu Hợp đồng mã .

    Ngoài ra còn có "PostSharp" cho phép bạn chỉ sử dụng các thuộc tính như thế này:

    Contact contact = new Contact { Name = "Abhinav"};
    var context = new DataContext();
    context.Contacts.Add(contact);
    context.SaveChanges(); // NullReferenceException at this line
    

    Bằng cách thực hiện điều đó và biến PostSharp thành một phần trong quá trình xây dựng của bạn

    public class DataContext : DbContext 
    {
        public DbSet<Contact> Contacts {get; set;}
    }
    
    sẽ được kiểm tra null khi chạy. Xem: Kiểm tra null PostSharp null

    Giải pháp mã đơn giản

    Hoặc bạn luôn có thể mã hóa cách tiếp cận của riêng mình bằng mã cũ đơn giản. Ví dụ ở đây là một cấu trúc mà bạn có thể sử dụng để bắt các tham chiếu null. Nó được mô phỏng theo khái niệm tương tự như

    public partial class Contact 
    {
        public string Name {get; set;}
    }
    
    : HttpContext

    Bạn sẽ sử dụng rất giống với cách bạn sẽ sử dụng

    public class MyController
    {
        private ServiceA serviceA;
        private ServiceB serviceB;
    
        public MyController(ServiceA serviceA, ServiceB serviceB)
        {
            this.serviceA = serviceA;
            this.serviceB = serviceB;
        }
    
        public void MyMethod()
        {
            // We don't need to check null because the dependency injection container 
            // injects it, provided you took care of bootstrapping it.
            var someObject = serviceA.DoThis();
        }
    }
    
    , ngoại trừ mục tiêu hoàn thành ngược lại - không cho phép NullReferenceException. Dưới đây là một số ví dụ: X

    X được ngầm định chuyển đến và từ NullReferenceException để bạn có thể sử dụng nó bất cứ nơi nào bạn cần. Ví dụ: bạn có thể truyền một đối tượng

    public X { get; set; }
    
    public void InvokeX()
    {
        X.DoSomething(); // if X value is null, you will get a NullReferenceException
    }
    
    cho một phương thức lấy
    //Using code contracts:
    [ContractInvariantMethod]
    protected void ObjectInvariant () 
    {
        Contract.Invariant ( X != null );
        //...
    }
    
    : NullReferenceException

    Như bạn có thể thấy ở trên như với nullable, bạn sẽ truy cập giá trị cơ bản thông qua thuộc tính

    string str = string.Empty;
    str.ToLower(); // throw null reference exception
    
    . Ngoài ra, bạn có thể sử dụng một diễn viên rõ ràng hoặc ẩn, bạn có thể xem một ví dụ với giá trị trả về bên dưới:
    Public Class Person {
        public string Name { get; set; }
    }
    Person objPerson;
    objPerson.Name  /// throw Null refernce Exception 
    

    Hoặc thậm chí bạn có thể sử dụng nó khi phương thức chỉ trả về String.Empty.ToLower() (trong trường hợp này là "") bằng cách thực hiện đúc. Ví dụ: đoạn mã sau sẽ giống như đoạn mã trên:

    ToLower()

    Kết hợp với tiện ích mở rộng

    Kết hợp Html.Partial với phương thức mở rộng và bạn có thể bao quát nhiều tình huống hơn nữa. Dưới đây là một ví dụ về phương thức mở rộng có thể trông như thế nào:

    Renderpage

    Và đây là một ví dụ về cách sử dụng nó:

    Object reference not set to an instance of an object

    GitHub

    Để bạn tham khảo, tôi đã cung cấp mã ở trên trên GitHub, bạn có thể tìm thấy nó tại:

    https://github.com/luisperezphd/NotNull

    Tính năng ngôn ngữ liên quan

    C # 6.0 đã giới thiệu "toán tử có điều kiện null" giúp điều này một chút. Với tính năng này, bạn có thể tham chiếu các đối tượng lồng nhau và nếu bất kỳ một trong số chúng là

    @{
        MyEntity M = new MyEntity();
    }
    @RenderPage("_MyOtherView.cshtml", M); // error in _MyOtherView, the Model was Null
    
    thì toàn bộ biểu thức trả về
    @{
        MyEntity M = new MyEntity();
    }
    @Html.Partial("_MyOtherView.cshtml", M);
    
    .

    Điều này làm giảm số lượng kiểm tra null bạn phải thực hiện trong một số trường hợp. Cú pháp là đặt một dấu hỏi trước mỗi dấu chấm. Lấy mã sau đây làm ví dụ:

    Html.Partial

    Hãy tưởng tượng rằng Html.Partial là một đối tượng của loại foreach có một tài sản được gọi là

    @inherits System.Web.Mvc.WebViewPage
    @{
        ViewBag.Title = "Entity Index";
        List<MyEntity> MyEntities = new List<MyEntity>();
        MyEntities.Add(new MyEntity());
        MyEntities.Add(new MyEntity());
        MyEntities.Add(new MyEntity());
    }
    <div>
        @{
            foreach(var M in MyEntities)
            {
                // Squiggly lines below. Hovering says: cannot convert method group 'partial' to non-delegate type Object, did you intend to envoke the Method?
                @Html.Partial("MyOtherView.cshtml");
            }
        }
    </div>
    
    , v.v. Nếu foreach,
    @foreach(var M in MyEntities){
        ...
    }
    
    , Html.Partial, hoặc @Html.PartialNull thì ArgumentNullExceptionnull0600350111101

    Đây là một tính năng tuyệt vời, nhưng nó cung cấp cho bạn ít thông tin hơn. Không rõ ràng trong số 4 là null.

    Được tích hợp như Nullable?

    C # có một tốc ký tuyệt vời cho ArgumentNullException, bạn có thể làm cho một cái gì đó không thể bằng cách đặt một dấu hỏi sau loại như vậy

    public void DoSomething(MyObject obj) {
        if(obj == null) 
        {
            throw new ArgumentNullException("obj", "Need a reference to obj.");
        }
    }
    
    .

    Sẽ thật tuyệt nếu C # có cấu trúc như Contract.Requires(obj != null) ở trên và có một tốc ký tương tự, có thể là dấu chấm than (!) để bạn có thể viết một cái gì đó như:

    public void DoSometing([NotNull] obj)
    
    .     
    22
    2017-10-29 09: 06: 44Z
    1. Không bao giờ ném NullReferenceException
      2016-03-06 20: 35: 21Z
    2. @ JohnSaunders tôi dám hỏi tại sao? (Nghiêm túc mặc dù tại sao?)
      2016/03/07 15: 29: 30Z
    3. NullReferenceException có nghĩa là bị CLR ném. Nó có nghĩa là một tham chiếu đến null đã xảy ra. Điều đó không có nghĩa là một tham chiếu đến null sẽ xảy ra ngoại trừ việc bạn khéo léo kiểm tra trước.
      2016/03/07 15: 43: 52Z
    4. Tôi thấy quan điểm của bạn về việc điều đó sẽ gây nhầm lẫn như thế nào. Tôi đã cập nhật nó thành một ngoại lệ thường xuyên cho ví dụ này và một ngoại lệ tùy chỉnh trong GitHub.
      2016/03/07 18: 41: 52Z
    5. Câu trả lời tuyệt vời cho câu hỏi cơ bản như vậy. Nó không quá tệ khi mã của bạn bị lỗi. Thật kinh khủng khi nó đến từ sâu bên trong một thư viện thương mại của bên thứ ba mà bạn đang dựa vào và bộ phận hỗ trợ khách hàng cứ khăng khăng rằng đó phải là mã của bạn gây ra sự cố. Và bạn không hoàn toàn chắc chắn là không và toàn bộ dự án sẽ dừng lại .. Tôi thực sự nghĩ rằng điều này có thể tạo ra một văn bia thích hợp cho bia mộ của tôi: "Tham chiếu đối tượng không được đặt thành một thể hiện của một đối tượng."
      2016-05-03 04: 01: 06Z

    Bạn có thể sửa lỗi NullReferenceException một cách rõ ràng bằng cách sử dụng Toán tử có điều kiện Null trong c # 6 và viết ít mã hơn để xử lý kiểm tra null.

    Nó được sử dụng để kiểm tra null trước khi thực hiện thao tác truy cập thành viên (?.) hoặc chỉ mục (? [).

    Ví dụ

    obj

    tương đương với:

    Nullable<T>

    Kết quả là tên sẽ là null khi p là null hoặc khi p.Spouse là null.

    Nếu không, tên biến sẽ được gán giá trị của p.Spouse.FirstName.

    Để biết thêm chi tiết: Null- Toán tử có điều kiện

        
    9
    2017-11-29 23: 19: 36Z

    Dòng lỗi "Tham chiếu đối tượng không được đặt thành phiên bản của đối tượng. "tuyên bố rằng bạn chưa gán đối tượng đối tượng cho tham chiếu đối tượng và bạn vẫn đang truy cập các phương thức /phương thức của đối tượng đó.

    ví dụ: giả sử bạn có một lớp được gọi là myClass và nó chứa một thuộc tính prop1.

    [System.Diagnostics.DebuggerNonUserCode]
    public struct NotNull<T> where T: class
    {
        private T _value;
    
        public T Value
        {
            get
            {
                if (_value == null)
                {
                    throw new Exception("null value not allowed");
                }
    
                return _value;
            }
            set
            {
                if (value == null)
                {
                    throw new Exception("null value not allowed.");
                }
    
                _value = value;
            }
        }
    
        public static implicit operator T(NotNull<T> notNullValue)
        {
            return notNullValue.Value;
        }
    
        public static implicit operator NotNull<T>(T value)
        {
            return new NotNull<T> { Value = value };
        }
    }
    

    Bây giờ bạn đang truy cập prop1 này trong một số lớp khác như dưới đây:

    Nullable<T>

    dòng trên ném lỗi vì tham chiếu của lớp myClass được khai báo nhưng không được khởi tạo hoặc một thể hiện của đối tượng không được gán cho tham chiếu của lớp đó.

    Để sửa lỗi này, bạn phải khởi tạo (gán đối tượng cho tham chiếu của lớp đó).

    null     
    8
    2017 /03-08 10: 58: 18Z
    1. Câu trả lời này đã được trả lời.
      2017 /03-08 11: 31: 26Z

    Thật thú vị, không có câu trả lời nào trên trang này đề cập đến hai trường hợp cạnh, hy vọng không ai bận tâm nếu tôi thêm chúng:

    Trường hợp cạnh # 1: truy cập đồng thời vào Từ điển

    Từ điển chung trong .NET không an toàn cho luồng và chúng đôi khi có thể ném

    NotNull<Person> person = null; // throws exception
    NotNull<Person> person = new Person(); // OK
    NotNull<Person> person = GetPerson(); // throws exception if GetPerson() returns null
    
    hoặc thậm chí (thường xuyên hơn) NotNull<T> khi bạn cố truy cập khóa từ hai luồng đồng thời. Trường hợp ngoại lệ khá sai lệch trong trường hợp này.

    Trường hợp cạnh # 2: mã không an toàn

    Nếu T bị ném bởi mã Person, bạn có thể xem các biến con trỏ của mình và kiểm tra xem chúng có phải là NotNull<Person> hay không. Đó là điều tương tự ("ngoại lệ con trỏ null"), nhưng trong mã không an toàn, các biến thường được chuyển thành loại giá trị /mảng, v.v., và bạn đập đầu vào tường, tự hỏi làm thế nào một loại giá trị có thể ném cái này ngoại lệ.

    (Một lý do khác cho việc không sử dụng mã không an toàn trừ khi bạn cần nó, nhân tiện)

        
    8
    2017-04-19 00: 08: 28Z
    1. Ví dụ từ điển của bạn không phải là trường hợp cạnh. Nếu đối tượng không phải là luồng an toàn, thì việc sử dụng nó từ nhiều luồng sẽ tạo ra kết quả ngẫu nhiên. Ví dụ mã không an toàn của bạn khác với
      Person person = new Person { Name = "John" };
      WriteName(person);
      
      public static void WriteName(NotNull<Person> person)
      {
          Console.WriteLine(person.Value.Name);
      }
      
      theo cách nào?
      2017-03-24 02: 03: 11Z

    Tham chiếu đối tượng NullReferenceException hoặc Object không được đặt thành phiên bản của đối tượng xảy ra khi một đối tượng của lớp bạn đang cố sử dụng không được khởi tạo. Ví dụ:

    Giả sử rằng bạn có một lớp có tên Sinh viên.

    Value

    Bây giờ, hãy xem xét một lớp khác nơi bạn đang cố truy xuất tên đầy đủ của học sinh.

    Person person = GetPerson();
    
    public static NotNull<Person> GetPerson()
    {
        return new Person { Name = "John" };
    }
    

    Như đã thấy trong đoạn mã trên, câu lệnh Student s - chỉ khai báo biến loại Sinh viên, lưu ý rằng lớp Sinh viên không được khởi tạo vào thời điểm này. Do đó, khi câu lệnh s.GetFullName () được thực thi, nó sẽ ném NullReferenceException.

        
    3
    2016-07-28 10: 52: 34Z

    Vâng, theo thuật ngữ đơn giản:

    Bạn đang cố truy cập một đối tượng không được tạo hoặc hiện không có trong bộ nhớ.

    Vậy làm thế nào để giải quyết vấn đề này:

    1. Gỡ lỗi và để trình gỡ lỗi phá vỡ ... Nó sẽ trực tiếp đưa bạn đến biến bị hỏng ... Bây giờ, nhiệm vụ của bạn chỉ là sửa lỗi này .. Sử dụng từ khóa mới ở nơi thích hợp.

    2. Nếu nó được gây ra trên một số lệnh cơ sở dữ liệu vì đối tượng không có mặt thì tất cả những gì bạn cần làm là kiểm tra null và xử lý nó:

      T
    3. Cái khó nhất .. nếu GC đã thu thập đối tượng rồi ... Điều này thường xảy ra nếu bạn đang cố gắng tìm một đối tượng bằng chuỗi ... Nghĩa là, tìm nó theo tên của đối tượng thì có thể xảy ra rằng GC có thể đã làm sạch nó. .. Điều này rất khó tìm và sẽ trở thành một vấn đề ... Một cách tốt hơn để giải quyết vấn đề này là kiểm tra null bất cứ khi nào cần thiết trong quá trình phát triển. Điều này sẽ giúp bạn tiết kiệm rất nhiều thời gian.

    Bằng cách tìm theo tên tôi có nghĩa là một số khung cho phép bạn FIndObjects sử dụng chuỗi và mã có thể trông như thế này: FindObject ("ObjectName");

        
    2
    2016-05-16 08: 34: 08Z
    1. Nếu bạn có một tham chiếu đến một đối tượng, thì GC không bao giờ xóa sạch nó
      2015-12-24 07: 51: 46Z
    2. nếu bạn sử dụng những thứ như FindObject ("Tên của đối tượng"), không có cách nào mà GC sẽ biết trước rằng bạn sẽ từ chối đối tượng đó .. đây là gì đang cố gắng khám phá .. những điều này xảy ra trong thời gian chạy
      2015-12-24 08: 11: 04Z
    3. Có một số khung cung cấp chức năng này trong C # như Unity. câu hỏi không có gì liên quan đến BCl. Tìm kiếm trên Internet trước khi phê bình có rất nhiều chức năng như chúng và để biết thông tin loại bạn thậm chí tôi sử dụng nó hàng ngày. Bây giờ xin vui lòng cho tôi biết làm thế nào để câu trả lời không làm bất cứ điều gì.
      2015-12-24 12: 35: 24Z
    4. docs .unity3d.com /ScriptReference /Hoài kiểm tra liên kết và sửa lỗi chính mình mr.expert: p
      2015-12-24 12: 54: 12Z
    5. Các ví dụ tôi thấy trong liên kết của bạn chỉ định kết quả của GameObject.Find cho trường thành viên. Đó là một tài liệu tham khảo và GC sẽ không thu thập nó cho đến khi đối tượng chứa được thu thập.
      2016-05-25 18: 00: 40Z

    Nếu chúng tôi xem xét các tình huống phổ biến có thể ném ngoại lệ này, truy cập các thuộc tính héo đối tượng ở trên cùng.

    Ví dụ:

    Person

    tại đây, nếu địa chỉ là null, thì bạn sẽ nhận được NullReferenceException.

    Vì vậy, như một thông lệ, chúng ta nên luôn sử dụng kiểm tra null, trước khi truy cập các thuộc tính trong các đối tượng đó (đặc biệt chung chung)

    Person person = (NotNull<Person>)GetPerson();
    
    public static Person GetPerson()
    {
        return new Person { Name = "John" };
    }
    
        
    0
    2017-08-24 05: 55: 22Z
    1. Điều này đã được trả lời nhiều lần.
      2017-08-26 03: 24: 14Z

    Theo nghĩa đen, cách dễ nhất để sửa lỗi NullReferenceExellect có hai cách. Nếu bạn có GameObject chẳng hạn với tập lệnh được đính kèm và một biến có tên rb (Rigidbody) thì biến này sẽ bắt đầu null khi bạn bắt đầu trò chơi của mình.
    Đây là lý do tại sao bạn nhận được NullReferenceExellect vì máy tính không có dữ liệu được lưu trữ trong biến đó.

    Tôi sẽ sử dụng biến RigidBody làm ví dụ.
    Chúng tôi có thể thêm dữ liệu thực sự dễ dàng thực sự theo một số cách:

    1. Thêm RigidBody vào đối tượng của bạn bằng AddComponent > Vật lý > Người cứng nhắc
      Sau đó đi vào tập lệnh của bạn và nhập NotNull<T>
      Dòng mã này hoạt động tốt nhất theo các chức năng
      [System.Diagnostics.DebuggerNonUserCode]
      public static class NotNullExtension
      {
          public static T NotNull<T>(this T @this) where T: class
          {
              if (@this == null)
              {
                  throw new Exception("null value not allowed");
              }
      
              return @this;
          }
      }
      
      hoặc
      var person = GetPerson().NotNull();
      
      của bạn.
    2. Bạn có thể thêm một thành phần theo chương trình và gán biến cùng lúc với một dòng mã: null

    Ghi chú thêm: Nếu bạn muốn thống nhất thêm một thành phần vào đối tượng của mình và bạn có thể đã quên thêm một thành phần, bạn có thể nhập null phía trên khai báo lớp của bạn (khoảng trống bên dưới tất cả các cách sử dụng của bạn).
    Tận hưởng và tận hưởng những trò chơi thú vị!

        
    0
    2017-11-14 20: 45: 02Z

    Nếu một người nhận được thông báo này trong khi lưu hoặc biên dịch bản dựng, chỉ cần đóng tất cả các tệp và sau đó mở bất kỳ tệp nào để biên dịch và lưu.

    Đối với tôi lý do là tôi đã đổi tên tệp và tệp cũ vẫn mở.

        
    - 1
    2017-10-14 18: 48: 08Z

    Để sử dụng các phương thức và thành viên của một đối tượng, trước tiên bạn phải tạo đối tượng đó. Nếu bạn không tạo nó (biến nên giữ đối tượng không được khởi tạo), nhưng bạn cố gắng sử dụng các phương thức hoặc biến đó sẽ gặp lỗi đó.

    Đôi khi bạn có thể quên khởi tạo.

    Đã chỉnh sửa: mới không thể trả về null, nhưng ngoại lệ của lửa khi không thành công. Từ lâu, đây là trường hợp của một số ngôn ngữ, nhưng không còn nữa. Cảm ơn @John Saunders đã chỉ ra điều đó.

        
    - 1
    2017-10-27 13: 56: 19Z
    1. var address = country?.State?.County?.City;
      
      không bao giờ trả về null
      2017-10-27 13: 00: 04Z

    Đây về cơ bản là ngoại lệ tham chiếu Null . Như Microsoft trạng thái-

      

    Một ngoại lệ NullReferenceException được đưa ra khi bạn cố gắng truy cập vào   thành viên của một loại có giá trị là null.

    Điều đó có nghĩa là gì?

    Điều đó có nghĩa là nếu bất kỳ thành viên nào không giữ bất kỳ giá trị nào và chúng tôi đang khiến thành viên đó thực hiện một số nhiệm vụ nhất định thì hệ thống chắc chắn sẽ ném một tin nhắn và nói -

    Cảnh Này, đợi đã, thành viên đó không có giá trị nên nó có thể thực hiện nhiệm vụ mà bạn đang giao nó. Riết

    Chính ngoại lệ nói rằng một cái gì đó đang được giới thiệusai lầm nhưng giá trị của nó không được thiết lập. Vì vậy, điều này biểu thị rằng nó chỉ xảy ra trong khi sử dụng các loại tham chiếu làm Loại giá trị là không thể rỗng.

    NullReferenceException sẽ không xảy ra nếu chúng tôi đang sử dụng các thành viên loại Giá trị.

    country

    Đoạn mã trên hiển thị chuỗi đơn giản được gán với giá trị null .

    Bây giờ, khi tôi cố in độ dài của chuỗi str , tôi nhận được Một ngoại lệ chưa được xử lý của loại 'System.NullReferenceException' xảy ra vì thành viên str đang trỏ đến null và không thể có bất kỳ độ dài nào của null.

    NullReferenceException cũng xảy ra khi chúng ta quên khởi tạo một loại tham chiếu.

    Giả sử tôi có một phương thức lớp và thành viên trong đó. Tôi đã không ngay lập tức lớp học của tôi mà chỉ đặt tên lớp học của tôi. Bây giờ nếu tôi cố gắng sử dụng phương thức, trình biên dịch sẽ đưa ra lỗi hoặc đưa ra cảnh báo (tùy thuộc vào trình biên dịch).

    Country

    Trình biên dịch cho mã ở trên gây ra lỗi mà biến obj không được chỉ định, điều đó biểu thị rằng biến của chúng tôi có giá trị null hoặc không có gì. Trình biên dịch cho mã ở trên làm phát sinh lỗi biến obj không được chỉ định, điều đó biểu thị rằng biến của chúng tôi có giá trị null hoặc không có gì.

    Tại sao nó xảy ra?

    • NullReferenceException phát sinh do lỗi của chúng tôi vì không kiểm tra giá trị đối tượng. Chúng tôi thường bỏ chọn các giá trị đối tượng trong quá trình phát triển mã.

    • Nó cũng phát sinh khi chúng ta quên khởi tạo các đối tượng của mình. Sử dụng các phương thức, thuộc tính, bộ sưu tập, v.v. có thể trả về hoặc đặt giá trị null cũng có thể là nguyên nhân của ngoại lệ này.

    Làm thế nào để tránh nó?

    Có nhiều cách và phương pháp khác nhau để tránh ngoại lệ nổi tiếng này:

    1. Kiểm tra rõ ràng: Chúng ta nên tuân thủ truyền thống kiểm tra các đối tượng, thuộc tính, phương thức, mảng và bộ sưu tập xem chúng có rỗng không. Điều này có thể được thực hiện đơn giản bằng cách sử dụng các câu lệnh có điều kiện như if-other if-other, v.v.

    2. Xử lý ngoại lệ: Một trong những cách quan trọng để quản lý ngoại lệ này. Sử dụng các khối thử-bắt-cuối đơn giản, chúng ta có thể kiểm soát ngoại lệ này và cũng duy trì nhật ký của nó. Điều này có thể rất hữu ích khi ứng dụng của bạn đang ở giai đoạn sản xuất.

    3. Toán tử Null: Toán tử Null Coalescing và toán tử điều kiện null cũng có thể được sử dụng một cách hữu ích trong khi đặt giá trị cho các đối tượng, biến, thuộc tính và trường.

    4. Trình gỡ lỗi: Đối với nhà phát triển, chúng tôi có vũ khí lớn để gỡ lỗi với chúng tôi. Nếu chúng ta phải đối mặt với NullReferenceException trong quá trình phát triển, chúng ta có thể sử dụng trình gỡ lỗi để đến nguồn của ngoại lệ.

    5. Phương thức được xây dựng

    Có nhiều câu trả lời hay ở đây. Bạn cũng có thể kiểm tra mô tả chi tiết hơn với các ví dụ trên blog .

    Hy vọng điều này cũng có ích!

        
    - 2
    2017-10-18 07: 31: 02Z
    1. Về cơ bản, bạn đã sao chép một nửa bài đăng trên blog đó và không thêm gì mới mà câu trả lời hiện tại không giải quyết.
      2017-07-18 14: 41: 29Z
    2. @ codecaster Có phải nó được sao chép khi bạn viết lại một bản tóm tắt từ blog của riêng bạn. Tôi biết câu trả lời của tôi không có gì mới và không có gì mới mà những câu trả lời trước không có nhưng tôi muốn đóng góp theo cách tinh vi hơn và để người khác hiểu theo cách tôi hiểu. Sẽ vui mừng ngay cả khi nó giúp một người duy nhất. Trong thiện chí.
      2017-07-18 18: 01: 29Z

    Có một kịch bản có thể xảy ra liên quan đến Lớp . Câu hỏi cuối cùng đã bị đóng trước khi tôi nêu rõ nghị quyết: https://stackoverflow.com/questions/43348009/unable-to-instantiate- class

    Coi chừng các lớp không khởi tạo: Nếu bất kỳ phần nào trong hàm tạo của bạn trong một lớp ném State thì lớp không khởi tạo. Trong trường hợp của tôi, nó đã cố lấy chuỗi kết nối từ web.config không tồn tại.

    Tôi đã khởi tạo một lớp:

    country

    Bên trong lớp là một cuộc gọi để lấy chuỗi kết nối từ State. Phần này của hàm tạo đã ném một ngoại lệ giá trị null nên County là null.

    Nếu bạn từng gặp tình huống một lớp không khởi tạo, hãy thử đảm bảo rằng không có phần nào của trình tạo lớp đang ném City. F-11 và bước qua lớp và đảm bảo không có null.

        
    - 5
    2017-05-23 10: 31: 36Z
    1. Các nhà xây dựng không bao giờ trả về null. Chúng có thể khởi tạo một đối tượng hoặc ném ngoại lệ.
      2017-04-11 21: 12: 13Z
    2. @ CodeCaster Tôi đã điều chỉnh lại toàn bộ câu trả lời với hy vọng sẽ đáp ứng mối quan tâm của bạn. Vấn đề mà tôi chưa thấy trong các câu trả lời khác là nếu bất kỳ phần nào của hàm tạo lớp ném một ngoại lệ thì nó sẽ khiến lớp không khởi tạo được. Mặc dù điều này rất có ý nghĩa với tôi nhưng nó không phải là một lựa chọn rõ ràng đối với tôi.
      2017-04-12 16: 13: 26Z
    3. Một lần nữa, điều này không thể xảy ra. Nếu hàm tạo này ném, dòng tiếp theo sẽ không thực thi.
      2017-04-13 05: 32: 54Z
    4. @ logixologist Hoàn toàn đồng ý với CC ở đây, câu trả lời này không có ý nghĩa gì khi nó đứng.
      2017-07-05 12: 36: 38Z
    null
nguồn đặt đây