2011-09-13 69 views
15

Tôi có một lớp Repository và một lớp dịch vụ như sau:Trình khởi tạo trường không thể tham chiếu trường, phương thức hoặc thuộc tính không tĩnh?

public class DinnerRepository 
{ 
    DinnerDataContext db = new DinnerDataContext(); 

    public Dinner GetDinner(int id) 
    { 
     return db.Dinners.SingleOrDefault(d => d.DinnerID == id); 
    } 

// Others Code   
} 



public class Service 
{ 
     DinnerRepository repo = new DinnerRepository(); 
     Dinner dinner = repo.GetDinner(5); 

// Other Code 
} 

này ném lỗi:

A field initializer cannot reference the non-static field, method, or property.

Mặc dù tôi đã intatiated Class DinnerRepository để lộ phương pháp của nó GetDinner() trong Dịch vụ Lớp học. Điều này làm việc tốt với mã dưới đây. Có bất kỳ thay thế cho nó hoặc nó là một thực hành tiêu chuẩn? Tôi không thể sử dụng phương pháp tĩnh ở đây ..

public class Service 
{ 

    public Service() 
    { 
     DinnerRepository repo = new DinnerRepository(); 
     Dinner dinner = repo.GetDinner(5); 
    } 

} 

Trả lời

18

Cá nhân tôi muốn chỉ khởi tạo các trường trong một constructor:

public class Service 
{ 
    private readonly DinnerRepository repo; 
    private readonly Dinner dinner; 

    public Service() 
    { 
     repo = new DinnerRepository(); 
     dinner = repo.GetDinner(5); 
    } 
} 

Lưu ý rằng điều này không giống như các mã mà bạn thấy ở phía dưới của câu hỏi, vì đó chỉ tuyên bố các biến số địa phương. Nếu bạn chỉ muốn biến cục bộ, điều đó là tốt - nhưng nếu bạn cần ví dụ biến, sau đó sử dụng mã như trên.

Về cơ bản, trình khởi tạo trường bị giới hạn ở những gì chúng có thể làm. Từ phần 10.5.5.2 của C# 4 spec:

A variable initializer for an instance field cannot reference the instance being created. Thus it is a compile-time error to reference this in a variable initializer, because it is a compile-time error for a variable initializer to reference any instance member through a simple-name.

(That "do đó" và "do đó" trông một cách sai lầm tròn với tôi - đó là bất hợp pháp để tham khảo một thành viên thông qua một đơn giản tên nó tài liệu tham khảo this - tôi sẽ ping Mads về nó -. nhưng đó là về cơ bản phần có liên quan)

+0

Vâng, phiên bản hiện tại đọc như "vì chúng tôi có lỗi thời gian biên dịch trên' tên đơn giản ', chúng tôi tham chiếu' this' là lỗi ", chứ không phải cách khác. – SWeko

+0

@JonSkeet Lý do cho hành vi này là các trường được khởi tạo trước hàm tạo. Vì vậy, không có thành viên cá thể khi bạn cố gắng khởi tạo các trường. Đó là lý do tại sao bạn không thể sử dụng chúng trước khi lớp được khởi tạo đúng không? – UfukSURMEN

+1

@ UfukSURMEN: Không thực sự ... đối tượng đã tồn tại, nhưng nó sẽ mời một số lỗi khá khó hiểu. (Đôi khi rất khó chịu, phải thừa nhận ...) –

2

Thậm chí nếu các biểu thức initializaton có bảo đảm là trong "textual order", nó là bất hợp pháp cho một thể hiện các lĩnh vực initializers to access the this reference, và bạn đang ngầm sử dụng nó trong

Dinner dinner = repo.GetDinner(5); 

tương đương với

Dinner dinner = this.repo.GetDinner(5); 

Các IMHO thực hành tốt nhất, là để dành khởi tạo lĩnh vực với các giá trị liên tục hoặc một tuyên bố đơn giản new. Bất cứ điều gì hairier hơn mà nên đi đến một nhà xây dựng.

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