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();
}
}
}
Oto kolejność, którą założyłem
- Początek konstruktora statycznego
- Koniec konstruktora statycznego
- Początek pliku main
- Początek MyMethod
- Koniec main
Teraz, w każdym scenariuszu, jeśli 4 zacznie się przed 2, mam przerąbane. Czy to możliwe?
c#
c#-4.0
static-constructor
om471987
źródło
źródło
Odpowiedzi:
Zadałeś tutaj tylko jedno pytanie, ale jest kilkanaście pytań, które powinieneś był zadać, więc odpowiem na wszystkie.
cctor
)Nie. Prawidłowa kolejność to:
Środowisko CLR może zmienić kolejność, w jakiej w niektórych przypadkach są uruchamiane inicjatory pól statycznych. Zobacz stronę Jona na ten temat, aby uzyskać szczegółowe informacje:
Różnice między konstruktorami statycznymi a inicjatorami typów
Tak. Jeśli sam cctor wywoła MyMethod, wtedy oczywiście MyMethod zostanie wywołana przed zakończeniem cctor.
Tak. Jeśli cctor używa innego typu, którego cctor wywołuje MyMethod, wówczas MyMethod zostanie wywołana przed zakończeniem działania cctor MyClass.
Nie.
Tak. Cctor zakończy się na jednym wątku, zanim będzie można wywołać metodę statyczną w dowolnym wątku.
Gwarantowane jest, że cctor zostanie wywołany najwyżej raz, niezależnie od liczby zaangażowanych wątków. Jeśli dwa wątki wywołują MyMethod „w tym samym czasie”, ścigają się. Jeden z nich przegrywa wyścig i blokuje do czasu, gdy na zwycięskiej nitce nie skończy się kreator MyClass.
Naprawdę.
Wtedy mamy klasyczny warunek odwrócenia kolejności blokowania. Twój program jest zakleszczony. Na zawsze.
Jeśli to boli, przestań to robić . Nigdy nie rób czegoś, co może zablokować cctor.
Nie są też dobre pomysły. Moja rada jest taka, że powinieneś znaleźć inny sposób, aby upewnić się, że warunki wstępne mające wpływ na bezpieczeństwo są spełnione.
źródło
Według MSDN , konstruktor statyczny:
Zatem konstruktor statyczny zostanie wywołany przed
MyClass.MyMethod()
wywołaniem metody statycznej (zakładając oczywiście, że nie zostanie on również wywołany podczas konstrukcji statycznej lub inicjalizacji pola statycznego).Jeśli robisz w tym coś asynchronicznego
static constructor
, to Twoim zadaniem jest to zsynchronizować.źródło
# 3 to właściwie # 1: inicjalizacja statyczna nie rozpoczyna się aż do pierwszego użycia klasy, do której należy.
Jest to możliwe, jeśli
MyMethod
jest wywoływana z konstruktora statycznego lub statycznego bloku inicjalizacji. Jeśli nie wywołujeszMyMethod
bezpośrednio lub pośrednio z konstruktora statycznego, wszystko powinno być w porządku.źródło
static
inicjalizację można w rzeczywistości wywołać przed pierwszym użyciem, w zależności od uprawnień do optymalizacji.beforefieldinit
Semantyka) są określane przez to, czy klasa C # ma konstruktor statyczny.Z dokumentacji (wyróżnienie moje):
źródło
Możesz zagwarantować, że liczba 4 będzie zawsze występować po 2 (jeśli nie utworzysz instancji swojej klasy z metody statycznej), jednak to samo nie dotyczy 1 i 3.
źródło
Konstruktor statyczny zostanie wywołany przed wykonaniem mymethod. Jeśli jednak masz spieprzone, jeśli 4 zostanie sprawdzone przed 2, proponuję ponownie przemyśleć swój projekt. I tak nie powinienem wykonywać skomplikowanych czynności w konstruktorze statycznym.
źródło
Środowisko CLR gwarantuje, że Konstruktor statyczny jest uruchamiany przed uzyskaniem dostępu do jakichkolwiek statycznych elementów członkowskich. Jednak twój projekt jest nieco śmierdzący. Byłoby łatwiej zrobić coś takiego:
static void Main(string[] args) { bool userIsAuthenticated = MyClass.AuthenticateUser(); if (userIsAuthenticated) MyClass.MyMethod(); }
W przypadku projektu, jeśli uwierzytelnianie nie powiedzie się, jedynym sposobem, aby zapobiec uruchomieniu MyMethod, jest zgłoszenie wyjątku.
źródło
Zapewniono, że konstruktor klasy statycznej został wywołany przed wykonaniem którejkolwiek z jej metod. Przykład:
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!"); } }
Wynik:
źródło
Oto rzeczywista kolejność, w jakiej wszystko się dzieje:
Main
MyClass
konstruktora statycznegoMyClass
konstruktora statycznegoMyMethod
Main
źródło
Lub możesz przejść przez debuger.
źródło