2011-03-01 46 views
6

Tôi có mã sau không được phép (lỗi dưới đây), tại sao?Tại sao thiết lập thuộc tính trong hàm tạo của một cấu trúc không hoạt động?

struct A 
    { 
     private int b; 

     public A(int x) 
     { 
      B = x; 
     } 
     public int B 
     { 
      get { return b; } 
      set { b=value; } 
     } 

    } 

tôi nhận được lỗi sau:

The 'this' object cannot be used before all of its fields are assigned to Field 'Test.x' must be fully assigned before control is returned to the caller

+0

kiểm tra câu trả lời của tôi, bạn sẽ nhận được ý tưởng về nó rõ ràng –

Trả lời

1

Thay đổi constructor của bạn để:

public A(int x) : 
    this() 
{ 
    B = x; 
} 

Như để "tại sao", hãy tham khảo 11.3.8 Constructors5.3 Definite assignment.

+0

Chỉ cần tự hỏi, sự khác biệt sẽ làm gì? –

+0

Điều này làm cho bạn giải quyết vấn đề – Dotnet

+0

@Gunner: Mã này sẽ xóa lỗi này Nếu không, bạn sẽ gặp lỗi khi không thể sử dụng đối tượng 'này' trước khi tất cả các trường của nó được gán – Dotnet

1

Từ MSDN "Trong một khai báo cấu trúc, các trường không thể được khởi tạo trừ khi chúng được khai báo là const hoặc tĩnh".

+0

Đó là tham chiếu đến trình khởi tạo trường; ** này không phải là ** bộ khởi tạo trường. –

4

Tất cả các biến của cấu trúc phải được gán chắc chắn trước khi bạn có thể sử dụng bất kỳ phương pháp hoặc thuộc tính nào. Có hai bản vá có thể ở đây:

1) Bạn rõ ràng có thể gọi các nhà xây dựng parameterless:

public A(int x) : this() 
{ 
    B = x; 
} 

2) Bạn có thể sử dụng lĩnh vực này thay vì tài sản:

public A(int x) 
{ 
    b = x; 
} 

Tất nhiên tùy chọn thứ hai chỉ hoạt động trong biểu mẫu hiện tại của bạn - bạn để sử dụng tùy chọn đầu tiên nếu bạn muốn thay đổi cấu trúc của mình để sử dụng thuộc tính tự động.

Tuy nhiên, quan trọng, bây giờ bạn có cấu trúc có thể thay đổi. Điều này hầu như luôn luôn là ý tưởng rất xấu . Tôi sẽ mạnh mong bạn sử dụng một cái gì đó giống như thay vì điều này:

struct A 
{ 
    private readonly int b; 

    public A(int x) 
    { 
     b = x; 
    } 

    public int B { get { return b; } } 
} 

EDIT: Thông tin chi tiết về việc tại sao mã gốc không hoạt động ...

Từ phần 11.3.8 của C# đặc tả :

If the struct instance constructor doesn't specify a constructor initializer, the this variable corresponds to an out parameter of the struct type

Bây giờ ban đầu đó sẽ không được chắc chắn được giao, có nghĩa là bạn không thể thực hiện bất kỳ hàm thành viên (bao gồm cả setters tài sản) cho đến khi tất cả những cái đầu tiên của cấu trúc con người xây dựng ed đã được ấn định rõ ràng. Trình biên dịch không biết hoặc cố gắng tính đến thực tế rằng trình thiết lập thuộc tính không cố gắng đọc từ một trường khác. Đó là tất cả để tránh đọc từ các lĩnh vực mà chưa được phân công rõ ràng.

+0

Tôi cũng không hiểu. Sự khác biệt giữa thiết lập với thuộc tính mà làm như vậy (b = value) và làm nó theo cách thủ công? Tuy nhiên tôi không thể thấy lý do tại sao B = x không hoạt động. Biến cấu trúc BTW là các trường hoặc tôi nên gọi chúng là biến? – Mocco

+0

@Cocodrilo - vì bạn không thể làm gì * với cấu trúc cho đến khi nó được khởi tạo đầy đủ, có thể bằng cách gọi hàm tạo mặc định (và, như nó xảy ra, giả mạo) hoặc có thể bằng cách gán tất cả các trường một cách rõ ràng. Bạn không thể truy cập một thuộc tính (là một phương thức) cho đến khi nó được thực hiện. "1" ở trên cho thấy tùy chọn đầu tiên (hàm tạo), "2" ở trên cho thấy tùy chọn "gán tất cả các trường". –

+0

@Cocodrilo và chỉ đến điểm thứ hai của Jon; các cấu trúc có thể thay đổi là mojo rất rất xấu. –

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