2009-03-18 13 views
8

Mã này có hành vi được xác định rõ trong C# không làm việc:Tại sao trong C# có vấn đề trật tự cho khởi tạo tĩnh?

class Foo 
{ 
    static List<int> to = new List<int>(from); // from is still null 
    static IEnumerable<int> from = Something(); 
} 

Lưu ý: Tôi không yêu cầu làm thế nào để khắc phục điều đó mã như I already known how to do that

sự biện minh cho điều này là gì? C# đã chạy kiểm tra thời gian để phát hiện truy cập đầu tiên tới các thành viên tĩnh. Tại sao không mở rộng điều này cho một điều mỗi thành viên và họ có chạy theo yêu cầu hoặc thậm chí tốt hơn có trình biên dịch tìm ra thứ tự tại thời gian biên dịch?

BTW: Tôi nghĩ cùng một câu hỏi (hoặc gần như giống nhau) cũng giữ cho các thành viên không tĩnh.

+1

Tôi nghĩ bạn trả lời chính mình bằng cách nói đây là 'hành vi được xác định rõ'. – mayu

Trả lời

6

tôi có thể hình dung một lập trình viên tùy thuộc vào thứ tự khởi do tác dụng phụ với tĩnh khác các lớp học. Bạn và tôi đều biết rằng tùy thuộc vào tác dụng phụ là hành vi xấu, nhưng nó không nhất thiết là bất hợp pháp.

Hãy xem xét một cái gì đó như thế này:

class Foo 
{ 
    static string header = Bar.GetHeader(); 
    static string version = Bar.GetVersion(); 
} 

Bar.GetVersion giả định rằng Bar.GetHeader đã được gọi. Nếu trình biên dịch được tự do thay đổi thứ tự khởi tạo, thì trình lập trình sẽ không thể đảm bảo thứ tự khởi tạo.

Xấu xí, được cấp, nhưng hoàn toàn hợp pháp. Nếu bạn hình dung các hiệu ứng bậc hai (tức làđược gọi là các phương thức tĩnh tự phụ thuộc vào các lớp có tác dụng phụ), bạn thấy rằng trình biên dịch không thể sắp xếp lại bất cứ điều gì một cách đáng tin cậy, cũng giống như không thể (nói chung) cho trình biên dịch sắp xếp thứ tự các cuộc gọi hàm trong hàm dựng tĩnh của bạn.

+0

Một điểm tốt và nó có thể là lý do. Điều đó nói rằng tôi nghĩ rằng "đánh giá theo thứ tự" cách là sai đường để giải quyết điều đó. Tôi nghĩ rằng sự khéo léo chính xác là để nói, "nếu trật tự quan trọng, khởi tạo trong một nhà xây dựng." và "Mã phụ thuộc vào thứ tự khởi tạo nội tuyến là bất hợp pháp, ngay cả khi nó chạy". – BCS

1

Tôi nghĩ rằng những gì bạn cần sử dụng là một hàm tạo tĩnh.

Giống như rất

class Foo 
{ 
    static List<int> to; 
    static IEnumerable<int> from; 

    static Foo() 
    { 
     from = Something(); 
     to = new List<int>(from); 
    } 
} 

Là tại sao C# không làm điều đó vào việc tiếp cận đầu tiên, tôi không thấy sự cần thiết rằng loại phức tạp khi có lựa chọn thay thế khác mà làm cho nó rõ ràng những gì đang xảy ra .

+0

Tôi nghĩ rằng bạn không đọc câu hỏi. – Samuel

+0

Tôi đã đọc câu hỏi. Hỏi tại sao C# làm một cái gì đó một cách, không bao giờ sẽ giúp bạn có được nhiều câu trả lời hữu ích. Câu trả lời của tôi là dọc theo dòng, tại sao nó sẽ khi bạn có thể làm điều này ... – Ray

+0

Hỏi lý do tại sao một cái gì đó hoạt động trong C# đã làm việc rất nhiều lần; hãy xem Jon Skeet biết bao nhiêu về cơ chế của C#. – Samuel

1

C# thực hiện kiểm tra thời gian chạy để phát hiện truy cập đầu tiên vào một lớp, nhưng không đặt lại khởi tạo tĩnh trong một lớp.

Các trường tĩnh được khởi tạo từ trên xuống dưới, theo sau là các hàm tạo tĩnh từ trên xuống dưới. Hoặc thay đổi thứ tự của các trường của bạn hoặc tạo một hàm tạo tĩnh và khởi tạo các trường từ tehre.

Xem Variable initializers trong thông số C# hoặc this article trên bộ khởi tạo .. Ngoài ra, câu hỏi Order of static constructors/initializers in C# có liên quan.

+0

Tôi đã hỏi câu hỏi đó: b Đồng thời xem nhận xét của tôi về Ray. Tôi/không/hỏi cách sửa mã đó. – BCS

+0

Vâng, bạn đã làm. :-) Tôi đoán tôi nên chú ý hơn! –

+0

"'Đã xảy ra sự cố, vui lòng liên hệ với quản trị viên của sys', Crud! Tôi sẽ làm nhưng tôi/quản trị viên của sys!" BCS

12

Trình khởi chạy chỉ là đường cú pháp. Trình biên dịch đặt mã đó trong .cctor khi nó biên dịch lớp của bạn, và nó pust chúng trong các lệnh mà chúng được đặt ra trong mã.

Nó không chạy bất kỳ séc nào, vì nó sẽ không có ý nghĩa. Bạn vẫn có thể có các chu kỳ khởi tạo, vì vậy nó sẽ không hoạt động.

Tôi viết blog về nó một số thời gian trước đây nếu bạn quan tâm:

+0

Đó là lý do chính: các chu kỳ khởi tạo mà trình biên dịch không thể giải quyết được. –

+0

Chu kỳ luôn luôn là một lỗi: Tôi muốn nhận được lỗi biên dịch hơn những gì bạn đang nhận được. Ngoài chu kỳ, tôi thấy không có vấn đề gì. +1 – BCS

+0

> "Trình biên dịch đặt mã đó vào .cctor." Chắc chắn điều này không thể đúng. Initializers được gọi theo thứ tự khác với các hàm tạo, phải không? – mayu