2012-02-22 45 views
79
namespace MyNameSpace 
{ 
    static class MyClass 
    { 
     static MyClass() 
     { 
      //Authentication process.. User needs to enter password 
     } 

     public static void MyMethod() 
     { 
      //Depends on successful completion of constructor 
     } 
    } 

    class Program 
    { 
     static void Main(string[] args) 
     { 
      MyClass.MyMethod(); 
     } 
    } 
} 

Dưới đây là trình tự mà tôi cho rằngPhương thức khởi tạo tĩnh hoạt động như thế nào?

  1. Bắt đầu constructor tĩnh
  2. End của constructor tĩnh
  3. Bắt đầu chính
  4. Bắt đầu MyMethod
  5. End của chính

Hiện tại trong mọi trường hợp nếu 4 sẽ bắt đầu trước khi 2 tôi bị say. Có thể không?

+8

Đây có phải là câu hỏi java hay C# không? Bạn đã đặt cả hai thẻ và tôi không nghĩ rằng đặc điểm kỹ thuật giống nhau trong hai ngôn ngữ. – ARRG

+0

Trong phần mở rộng của tôi, nó giống với cả hai .. Nhưng tôi là C# guy .. Sry cho rằng – om471987

+4

Java không có một hàm tạo tĩnh theo cùng một cách, chỉ các khối tĩnh để khởi tạo tĩnh. static {// do something ...} – deraj

Trả lời

214

Bạn chỉ hỏi một câu hỏi tại đây nhưng có một tá câu hỏi mà bạn nên đã hỏi, vì vậy tôi sẽ trả lời tất cả.

Dưới đây là trình tự mà tôi cho rằng

  1. Bắt đầu constructor lớp (còn gọi là cctor)
  2. Cuối cctor
  3. đầu Main
  4. đầu MyMethod

Điều này có đúng không?

số Trình tự đúng là:

  1. Bắt đầu cctor cho Chương trình, nếu có. Không có.
  2. Kết thúc cctor cho Chương trình, nếu có. Không có.
  3. Bắt đầu Main
  4. Bắt đầu cctor cho MyClass
  5. Cuối cctor cho MyClass
  6. Bắt đầu MyClass.MyMethod

gì nếu có một lĩnh vực initializer tĩnh?

CLR được phép thay đổi thứ tự khởi tạo trường tĩnh trong một số trường hợp. Xem trang Jon về chủ đề để biết chi tiết:

The differences between static constructors and type initializers

Có bao giờ có thể cho một phương pháp tĩnh như MyMethod được gọi trước khi cctor của lớp đó hoàn thành?

Có.Nếu chính cctor gọi MyMethod thì rõ ràng MyMethod sẽ được gọi trước khi cctor hoàn tất.

CCtor không gọi MyMethod. Có bao giờ có thể cho một phương pháp tĩnh như MyMethod để được gọi trước khi cctor của MyClass hoàn thành?

Có. Nếu CCtor sử dụng một kiểu khác mà CCtor gọi MyMethod thì MyMethod sẽ được gọi trước khi MyClass CCtor hoàn tất.

Không có cctors gọi MyMethod, trực tiếp hoặc gián tiếp! Bây giờ là nó có thể bao giờ có thể cho một phương pháp tĩnh như MyMethod để được gọi trước khi các cctor của MyClass hoàn thành?

số

Có phải đó là vẫn đúng ngay cả khi có nhiều chủ đề liên quan?

Có. CCtor sẽ kết thúc trên một luồng trước khi phương thức tĩnh có thể được gọi trên bất kỳ luồng nào.

CCtor có thể được gọi nhiều lần không? Giả sử hai luồng đều làm cho cctor chạy.

CCtor được đảm bảo được gọi tối đa một lần, cho dù có bao nhiêu chủ đề. Nếu hai chủ đề gọi MyMethod "cùng một lúc" thì họ chạy đua. Một trong số họ mất cuộc đua và chặn cho đến khi người quản lý MyClass hoàn thành chuỗi chiến thắng.

Chủ đề bị mất khối cho đến khi cctor được thực hiện? Thực sự?

Thực sự.

Vì vậy, những gì nếu cctor trên thread chiến thắng gọi mã mà khối trên một khóa trước đây được thực hiện bởi mất chủ đề?

Sau đó, bạn có điều kiện đảo ngược lệnh khóa cổ điển. Chương trình deadlocks của bạn. Mãi mãi.

Điều đó có vẻ nguy hiểm. Làm thế nào tôi có thể tránh được bế tắc?

Nếu bị đau khi bạn làm như vậy thì ngừng làm điều đó. Không bao giờ làm điều gì đó có thể chặn trong một người quản lý.

Bạn nên dựa vào ngữ nghĩa khởi tạo của cctor để thực thi các yêu cầu bảo mật phức tạp? Và có một ý tưởng hay để có một người giao dịch có tương tác với người dùng không?

Không phải là ý tưởng hay. Lời khuyên của tôi là bạn nên tìm một cách khác để đảm bảo rằng các điều kiện tiên quyết bảo mật tác động của các phương pháp của bạn được đáp ứng.

+4

Eric, tôi tò mò tại sao bạn thay thế "constructor tĩnh" với "class constructor" hoặc "cctor" trong câu trả lời này. Có sử dụng "constructor tĩnh" không đúng khi đề cập đến một cctor không? – phoog

+6

@phoog: Tôi muốn nhất quán trong việc sử dụng thuật ngữ, vì vậy tôi đã chọn thuật ngữ ngắn nhất. "Hàm khởi tạo tĩnh" và "hàm tạo lớp" đều tốt. Như một chi tiết thực hiện, hàm tạo tĩnh của một kiểu được phát ra như là một phương thức đặc biệt được gọi là ".cctor", do đó, nó là phổ biến để tham chiếu đến một hàm tạo như là một "con trỏ". Tôi đã viết trong một bối cảnh chính thức hơn, tôi sẽ sử dụng một trong những thuật ngữ dài hơn. –

10

Số 3 thực sự là # 1: khởi tạo tĩnh không bắt đầu cho đến lần sử dụng đầu tiên của lớp mà nó thuộc về.

Có thể nếu MyMethod được gọi từ hàm dựng tĩnh hoặc khối khởi tạo tĩnh. Nếu bạn không gọi MyMethod trực tiếp hoặc gián tiếp từ hàm dựng tĩnh của mình, bạn sẽ ổn thôi.

+0

Giống như một lưu ý, đó là sự hiểu biết của tôi rằng khởi tạo 'tĩnh' thực sự có thể được gọi trước khi sử dụng lần đầu tiên tùy thuộc vào điều kiện để tối ưu hóa. –

+0

@JamesMichaelHare theo tài liệu MS, ["Việc thi hành một hàm dựng tĩnh được kích hoạt bởi các sự kiện đầu tiên xảy ra trong một miền ứng dụng: (1) Một cá thể của lớp được tạo ra. các thành viên của lớp được tham chiếu. "] (http://msdn.microsoft.com/en-us/library/aa645612%28v=vs.71%29.aspx) – dasblinkenlight

+1

Đối với một hàm dựng tĩnh, đúng, nhưng để khởi tạo tĩnh là quan điểm của tôi. Xin lỗi, có lẽ tôi đã chỉ cần chọn nits trên cụm từ 'khởi tạo tĩnh không bắt đầu ...' đó là đúng cho xây dựng tĩnh, nhưng không phải nếu lớp không có một constructor tĩnh, sau đó khởi tạo tĩnh có thể xảy ra trước. –

22

Theo MSDN, một constructor tĩnh:

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

Vì vậy, các nhà xây dựng tĩnh sẽ được gọi trước khi phương pháp tĩnh MyClass.MyMethod() được gọi (giả sử không cũng gọi trong quá trình thi tĩnh hoặc khởi lĩnh vực tĩnh dĩ nhiên).

Bây giờ, nếu bạn đang làm bất cứ điều gì không đồng bộ trong đó static constructor, thì đó là công việc của bạn để đồng bộ hóa điều đó.

+7

Nếu bạn đang làm bất cứ điều gì không đồng bộ liên quan đến chuỗi thứ hai trong một hàm tạo tĩnh , * bạn đang ở trong một thế giới của nỗi đau *. Không có gì làm cho deadlocks nhanh hơn. Xem http://stackoverflow.com/a/8883117/88656 để biết ví dụ. –

+0

@Eric: đã đồng ý ... Tôi sẽ không muốn làm điều đó, nhưng không chắc chắn hình thành ví dụ của ông chính xác những gì ông muốn được hoàn thành bởi thời gian MyMethod được gọi là ... –

8

Từ (tôi nhấn mạnh) documentation:

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

2

Bạn có thể đảm bảo 4 sẽ luôn luôn đến sau 2 (nếu bạn không tạo ra một thể hiện của lớp học của bạn từ phương pháp tĩnh của bạn), tuy nhiên điều này cũng không đúng đối với 1 và 3.

2

Các tĩnh constructor sẽ được gọi trước khi mymethod được thực hiện. Tuy nhiên nếu bạn đang say nếu 4 được gọi trước 2 thì tôi đề nghị bạn nghĩ lại thiết kế của bạn. Không nên làm công cụ phức tạp trong một constructor tĩnh anyway.

2

CLR đảm bảo rằng hàm tạo tĩnh chạy trước khi bất kỳ thành viên tĩnh nào được truy cập. Tuy nhiên, thiết kế của bạn có một chút mùi. Sẽ đơn giản hơn để làm một cái gì đó như thế này:

static void Main(string[] args) 
{ 
    bool userIsAuthenticated = MyClass.AuthenticateUser(); 
    if (userIsAuthenticated) 
     MyClass.MyMethod(); 
} 

Với thiết kế của bạn, nếu thẩm định thất bại, cách duy nhất để ngăn chặn MyMethod chạy là bằng cách ném một ngoại lệ.

2

Đảm bảo rằng hàm tạo của lớp tĩnh đã được gọi trước khi bất kỳ phương thức nào của nó được thực thi. Ví dụ:

class Program 
{ 
    static void Main(string[] args) 
    { 
     Console.WriteLine("Press enter"); 
     Console.ReadLine(); 
     Boop.SayHi(); 
     Boop.SayHi(); 
     Console.ReadLine(); 
    } 

} 

static class Boop 
{ 
    static Boop() 
    { 
     Console.WriteLine("Hi incoming ..."); 
    } 

    public static void SayHi() 
    { 
     Console.WriteLine("Hi there!"); 
    } 
} 

Output:

Nhấn Enter

// sau khi nhấn enter

Hi đến ...

Hi there!

Hi there!

+0

sử dụng Hệ thống; không gian tên MyNameSpace { Chương trình lớp { khoảng trống tĩnh Main (string [] args) { Console.WriteLine ("Đã nhập trong chính"); Boop.SayHi(); Boop.SayHi(); } } lớp tĩnh Boop { static Boop() { Console.Read(); Console.WriteLine ("Khóa constructor đã nhập"); } void tĩnh công cộng SayHi() { Console.WriteLine ("Phương thức được gọi"); } } } vâng chương trình này giúp hiểu rõ hơn – om471987

+0

Có thể. Tuy nhiên, lần sau đăng câu trả lời là một câu trả lời. Nó hữu ích hơn và có thể nhìn thấy sau đó. – haiyyu

0

Hoặc bạn có thể xem qua trong trình gỡ lỗi.

+0

Có, tôi đã chắc chắn về con đường hạnh phúc .. Tôi muốn biết từng điều kiện ... – om471987

1

Dưới đây là thứ tự thực tế, trong đó mọi thứ đi xuống:

  1. Bắt đầu Main
  2. Bắt đầu của tĩnh MyClass constructor
  3. End của tĩnh MyClass constructor
  4. Bắt đầu MyMethod
  5. Kết thúc của Main
Các vấn đề liên quan