2015-06-03 16 views
17

Testcase sau ném một ngoại lệ tham chiếu null, khi nó cố gắng gán Id cho một đối tượng là null, vì mã thiếu "R mới" trước bộ khởi tạo đối tượng.Tại sao bộ khởi tạo đối tượng lồng nhau này ném một ngoại lệ tham chiếu null?

Tại sao điều này không bị trình biên dịch bắt? Tại sao nó được cho phép, trong đó các trường hợp sử dụng sẽ là một cấu trúc có ý nghĩa?

[TestClass] 
public class ThrowAway 
{ 
    public class H 
    { 
     public int Id { get; set; } 
    } 

    public class R 
    { 
     public H Header { get; set; } 
    } 

    [TestMethod] 
    public void ThrowsException() 
    { 
     var request = new R 
         { 
          Header = 
          { 
           Id = 1 
          }, 
         }; 
    } 
} 
+0

Bạn phải khởi tạo thuộc tính Tiêu đề của đối tượng R của mình. 'var request = new R {Header = new H {Id = 1}}; ' – Styxxy

+3

Câu hỏi rất thú vị ... nó thậm chí không rõ ràng nếu trình biên dịch đang thực hiện một dàn diễn viên hay cái gì ... – xanatos

+3

Câu hỏi rất thú vị, nhưng tiêu đề cực kỳ nghèo nàn theo ý kiến ​​của tôi. Bạn có cân nhắc việc thay đổi nó thành câu hỏi thực tế bạn đang hỏi không? – julealgon

Trả lời

18

Trình biên dịch không đưa ra một cảnh báo vì bạn có thể có:

public class R 
{ 
    public H Header { get; set; } 

    public R() 
    { 
     Header = new H(); 
    } 
} 

nên Header có thể được khởi tạo bởi một ai đó/cái gì đó. Giải quyết nếu có ai/cái gì đó sẽ khởi Header là một vấn đề phức tạp (có lẽ tương tự như vấn đề Tạm dừng) ... Không cái gì mà một trình biên dịch muốn giải quyết cho bạn :-)

Từ thông số kỹ thuật C#:

Trình khởi tạo thành viên chỉ định trình khởi tạo đối tượng sau dấu bằng là một khởi tạo đối tượng lồng nhau, tức là khởi tạo đối tượng được nhúng. Thay vì gán giá trị mới cho trường hoặc thuộc tính, các nhiệm vụ trong bộ khởi tạo đối tượng lồng nhau được coi là gán cho thành viên của trường hoặc thuộc tính. Không thể áp dụng bộ khởi tạo đối tượng lồng nhau cho thuộc tính có loại giá trị hoặc cho trường chỉ đọc có loại giá trị.

Chúng tôi đang trong trường hợp khởi tạo lồng nhau và xem phần được in đậm. Tôi không biết.

Bây giờ, lưu ý rằng new R { } là, bằng C# spec, một 7.6.10.1 Object creation expressions tiếp theo là một object-initializer, trong khi Header = { } là một "tinh khiết" 7.6.10.2 Object initializers.

+1

Cùng một câu hỏi với bài đăng khác ở đây - tại sao nó cho phép 'Header = {Id = 1}'? Điều này có vẻ đồng bằng sai, phải không? – Andrei

+0

@Andrei Ít nhất tôi đã giải thích * Tại sao điều này không bị bắt bởi trình biên dịch? * :-) – xanatos

+0

Xin lỗi, tôi vẫn không hiểu. Không cố gắng tranh cãi, bản thân tôi cũng rất tò mò. Trình biên dịch nên đã thất bại trên cú pháp như vậy, không có vấn đề nếu có khởi tạo trong ctor, phải không? – Andrei

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