2010-05-27 36 views
11

Đầu ra từ chương trình sau là:Hàm tạo tĩnh có thể chạy sau hàm tạo không tĩnh. Đây có phải là lỗi trình biên dịch không?

Non-Static 
Static 
Non-Static 

Đây có phải là lỗi trình biên dịch không? Tôi dự kiến:

Static 
Non-Static 
Non-Static 

vì tôi nghĩ hàm tạo tĩnh luôn được gọi trước hàm tạo không tĩnh.

Tôi đã thử nghiệm điều này với Visual Studio 2010 bằng cách sử dụng cả hai .net 3.5 và .net 4.0.

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 

namespace StaticConstructorBug 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      var mc = new MyClass(); 

      Console.ReadKey(); 
     } 
    } 

    public class MyClass 
    { 
     public MyClass() 
     { 
      Console.WriteLine("Non-static"); 
     } 

     static MyClass() 
     { 
      Console.WriteLine("Static"); 
     } 

     public static MyClass aVar = new MyClass(); 
    } 
} 
+0

bạn có thể giải thích lý do tại sao bạn mong đợi đó? Bởi vì đó không phải là những gì các đặc điểm kỹ thuật nói để mong đợi. –

Trả lời

11

Xem ECMA 334 §17.4.5.1:

17.4.5.1 lĩnh vực tĩnh khởi

Trường tĩnh biến initializers của một khai báo lớp tương ứng với một chuỗi của bài tập đó là thực hiện trong thứ tự văn bản trong đó chúng xuất hiện trong tuyên bố lớp học. Nếu một hàm tạo tĩnh (§17.11) tồn tại trong lớp, việc thực thi trình khởi tạo trường tĩnh xảy ra ngay trước khi thực hiện hàm tạo tĩnh đó. Nếu không, initializers lĩnh vực tĩnh được thực hiện tại một thời gian thực hiện phụ thuộc vào trước khi sử dụng đầu tiên của một trường tĩnh của lớp đó

Cụ thể là: "thực hiện các initializers lĩnh vực tĩnh xảy ra ngay trước khi thực hiện mà constructor tĩnh ".

static MyClass aVar của bạn phải được khởi tạo trước khi hàm tạo tĩnh của bạn thực thi (hoặc ít nhất, nó phải xuất hiện theo cách đó). Nếu không có thành viên tĩnh đó, hàm dựng tĩnh nên được gọi trước bất kỳ hàm tạo non-static nào.

Nếu bạn vẫn muốn một trang đơn lẻ MyClass, bạn có thể đặt nó trong một lớp chứa và tham chiếu đến nó bằng cách sử dụng, ví dụ::

public static class MyClassSingleton 
{ 
    public static MyClass aVar = new MyClass(); 
} 
1

public static MyClass aVar = new MyClass(); này là một phần của hàm tạo tĩnh của bạn. Nếu bạn nhìn vào nó với phản xạ, bạn sẽ thấy như sau:

static MyClass() 
{ 
    aVar = new Program.MyClass(); 
    Console.WriteLine("Static"); 
} 

Vì vậy, kết quả của bạn phải rõ ràng bây giờ.

0

Từ MSDN Link:

Một constructor tĩnh được gọi là tự động để khởi tạo lớp trước khi trường hợp đầu tiên được tạo ra hoặc bất kỳ thành viên tĩnh được tham chiếu.

Tôi đoán đây là do sự khởi tạo tĩnh của thể hiện trên dòng cuối cùng, nhưng theo MSDN, hàm tạo tĩnh nên xảy ra trước khi thể hiện đầu tiên được gọi.

+0

Vâng, do đó, constructor tĩnh được gọi, nó khởi tạo thành viên dữ liệu (được xây dựng với constructor bình thường), sau đó điều khiển quay trở lại vào constructor tĩnh do người dùng định nghĩa, nơi anh ta in ra dòng. – Puppy

5

Nó được gây ra bởi dòng public static MyClass aVar = new MyClass();.

Thực tế, aVar = new MyClass(); được thêm vào bộ tạo sóng tĩnh. Vì vậy, constructor tĩnh của bạn:

static MyClass() { 
    Console.WriteLine("Static"); 
} 

được thay đổi thành:

static MyClass() { 
    aVar = new MyClass(); // this will run instance contstructor and prints "Non-Static" 
    Console.WriteLine("Static"); 
} 
Các vấn đề liên quan