2011-09-23 18 views
10

Tôi có một quan sát về cấu trúc. Khi tôi tuyên bố một tài sản trong Struct và nếu tôi không khởi tạo Struct sau đó nó mang lại cho tôi những lỗi dưới đây - "Sử dụng unassigned empStruct biến cục bộ"Trình biên dịch đưa ra lỗi khi cấu trúc không được khởi tạo và nếu chúng ta cố truy cập thuộc tính nhưng không phải với biến số

PSeduo số-

struct EmpStruct 
{ 
    private int firstNumber; 
    public int FirstNumber 
    { 
     get { return firstNumber; } 
     set { firstNumber = value; } 
    } 

    public int SecondNumber; 

} 

Program.cs-

EmpStruct empStruct; 
empStruct.FirstNumber = 5; 

Nhưng khi tôi khai báo biến công khai thì mã trên hoạt động.

EmpStruct empStruct; 
empStruct.SecondNumber; 

Vì vậy, câu hỏi của tôi là lý do tại sao trình biên dịch không đưa ra lỗi khi tôi cố truy cập biến. (Trong trường hợp lớp học sẽ đưa ra lỗi).

+3

Ai xuống hạng tất cả các câu trả lời, để lại nhận xét về lý do chúng không chính xác. Tôi upvoting họ, khi họ có ý nghĩa dựa trên bài viết của Punit ... –

+1

@ bemused: Họ đều sai. Và tôi đã để lại bình luận giải thích tại sao. – jason

Trả lời

11

Có một số lượng lớn sự nhầm lẫn trong chuỗi này.

Nguyên tắc là: cho đến khi tất cả các trường của một thể hiện của struct chắc chắn được gán, bạn không thể gọi bất kỳ thuộc tính hoặc phương thức nào trên cá thể.

Đây là lý do tại sao khối mã đầu tiên của bạn sẽ không biên dịch. Bạn đang truy cập vào một thuộc tính mà không cần gán tất cả các trường.

Khối biên dịch mã thứ hai vì không sao để truy cập một trường mà không có tất cả các trường chắc chắn được gán.

Một cách để chắc chắn gán một struct là để nói

EmpStruct empStruct = new EmpStruct(); 

này gọi các nhà xây dựng parameterless mặc định cho EmpStruct mà chắc chắn sẽ gán tất cả các lĩnh vực.

Phần có liên quan của đặc điểm kỹ thuật là §5.3 về Phân định xác định. Và từ ví dụ trong §11.3.8

Không có chức năng thành viên dụ (bao gồm cả bộ truy xuất thiết lập cho các thuộc tính XY) có thể được gọi đến khi tất cả các lĩnh vực của cấu trúc được xây dựng đã được chắc chắn được giao.

Nó sẽ là hữu ích hơn (e hèm, Eric Lippert!) Nếu thông điệp biên dịch lỗi là dọc theo dòng của

Sử dụng không chắc chắn được gán biến địa phương empStruct.

Sau đó, sẽ trở nên rõ ràng những gì cần tìm kiếm trong đặc điểm kỹ thuật hoặc trên Google.

Bây giờ, hãy lưu ý rằng bạn đã xác định cấu trúc có thể thay đổi. Điều này là nguy hiểm, và cái ác. Bạn không nên làm điều đó. Thay vào đó, hãy thêm một hàm tạo công khai cho phép bạn chỉ định rõ ràng firstNumbersecondNumber và xóa công cụ đặt công khai khỏi EmpStruct.FirstNumber.

+0

+1, Thu thập thông tin tốt về quyền truy cập thuộc tính! – sll

+0

Cảm ơn bạn đã xóa luồng. Tôi đoán đó là từ ngữ của câu hỏi khiến mọi người bối rối. –

+0

cảm ơn ý nghĩa – Punit

3

Về lĩnh vực ngôn ngữ C# Thông số kỹ thuật nói:

10.5.4 Dòng khởi

Giá trị ban đầu của một trường, cho dù đó là một lĩnh vực tĩnh hoặc một lĩnh vực dụ, là giá trị mặc định (§5.2) của kiểu trường. Đó là không thể quan sát giá trị của một lĩnh vực trước khi mặc định này khởi đã xảy ra, và một lĩnh vực là như vậy, không bao giờ “uninitialized

11.3.4 Giá trị mặc định

Tuy nhiên, kể từ cấu trúc là các kiểu giá trị không thể rỗng, giá trị mặc định của cấu trúc là giá trị được tạo bằng cách đặt tất cả các trường giá trị loại giá trị mặc định của chúng và tất cả các trường loại tham chiếu thành null. Giá trị mặc định của một struct tương ứng với giá trị trả về bởi hàm tạo mặc định của cấu trúc (§4.1.2).

PS: trong trường hợp của lớp nó mang lại cho lỗi vì loại tài liệu tham khảo có giá trị mặc định là null

+0

Điều này không liên quan. Nó không giải thích lý do cho lỗi. – jason

+0

@ Jason: nó có liên quan về trường hợp và trường hợp lớp học, nhưng không phải là một lỗi liên quan đến tài sản. Vẫn không thể tìm thấy câu trả lời trong đặc điểm kỹ thuật – sll

+0

Tôi xin lỗi, nó không liên quan chút nào. Lý do cho lỗi phải làm với việc thiếu phân bổ định nghĩa cho 'EmpStruct'. Các phần từ đặc điểm kỹ thuật mà bạn trích dẫn không tham chiếu đến phân bổ xác định. Xem §5.3 và §11.3.8. – jason

1

Trong ví dụ đầu tiên của bạn, mã không làm việc vì các biến địa phương phải được khởi tạo trước khi bạn có thể sử dụng chúng . Không có giá trị mặc định; chúng phải được khởi tạo trước. Bạn luôn phải khởi tạo mọi biến cục bộ trước khi có thể sử dụng nó. Ví dụ:

EmpStruct empStruct = new EmpStruct(); 
empStruct.FirstNumber = 5; 

Các trường trong một lớp không có cùng giới hạn này. Nếu bạn không khởi tạo chúng một cách rõ ràng, chúng sẽ tự động được khởi tạo với các giá trị mặc định. Thực tế, thời gian chạy tự động gọi là "EmpStruct() mới" trên trường trong lớp của bạn. Đó là lý do tại sao ví dụ thứ hai của bạn hoạt động.

+0

Điều này không có ý nghĩa gì cả.Tại sao trình biên dịch gọi là "EmpStruct' mới trong khối thứ hai chứ không phải là khối đầu tiên? Câu trả lời này không giải thích tại sao có sự khác biệt giữa hai khối mã. – jason

+0

Ah ... Tôi nghĩ rằng tôi đã gặp khó khăn trong việc hiểu câu hỏi ban đầu ... Nghĩ rằng anh ta đang nói về việc sử dụng một cấu trúc như một biến cục bộ so với sử dụng một cấu trúc như một trường. –

1

Một vài mẫu mã có thể giúp làm rõ điều này tốt hơn:

// This works because you assign both fields before accessing anything 
EmpStruct empStruct; 
empStruct.SecondNumber = 2; 
empStruct.firstNumber = 1; // I made this public 
empStruct.FirstNumber = 3; 
Console.WriteLine(empStruct.FirstNumber); 
Console.WriteLine(empStruct.SecondNumber); 

// This fails because you can't use properties before assigning all the variables 
EmpStruct empStruct; 
empStruct.SecondNumber = 2; 
empStruct.FirstNumber = 3; 

// This works because you are only accessing a field that the compiler knows you've assigned 
EmpStruct empStruct; 
empStruct.SecondNumber = 2; 
Console.WriteLine(empStruct.SecondNumber); 

// This fails because you haven't assigned the field before it gets accessed. 
EmpStruct empStruct; 
Console.WriteLine(empStruct.SecondNumber); 

Vấn đề là, trình biên dịch biết chính xác những gì sẽ xảy ra khi bạn gán một lĩnh vực. Nhưng khi bạn chỉ định thuộc tính, có thể truy cập bất kỳ số trường nào khác trên struct. Trình biên dịch không biết chắc chắn. Vì vậy, nó đòi hỏi bạn phải có tất cả các lĩnh vực được giao trước khi bạn có thể truy cập một tài sản.

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