정적 생성자는 어떻게 작동합니까?
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();
}
}
}
내가 가정 한 순서는 다음과 같습니다.
- 정적 생성자의 시작
- 정적 생성자의 끝
- 메인 시작
- MyMethod 시작
- 메인 끝
이제 어떤 시나리오에서든 4가 2 이전에 시작되면 나는 망했다. 가능합니까?
여기에 한 가지 질문 만 하셨는데 물어 보셨 어야 할 질문이 열두 개 정도 있으니 모두 대답하겠습니다.
내가 가정 한 순서는 다음과 같습니다.
- 클래스 생성자 시작 (라고도 함
cctor
) - cctor의 끝
- 메인 시작
- MyMethod 시작
이 올바른지?
아니요. 올바른 순서는 다음과 같습니다.
- 프로그램에 대한 cctor 시작 (있는 경우). 없기.
- 프로그램에 대한 cctor의 끝 (있는 경우). 없기.
- 메인 시작
- MyClass에 대한 cctor 시작
- MyClass에 대한 cctor의 끝
- MyClass.MyMethod 시작
정적 필드 이니셜 라이저가 있으면 어떻게됩니까?
CLR은 경우에 따라 정적 필드 이니셜 라이저가 실행되는 순서를 변경할 수 있습니다. 자세한 내용은 주제에 대한 Jon의 페이지를 참조하십시오.
MyMethod
해당 클래스의 cctor가 완료되기 전에 같은 정적 메서드 를 호출 할 수 있습니까?
예. cctor 자체가 MyMethod를 호출하면 cctor가 완료되기 전에 분명히 MyMethod가 호출됩니다.
cctor는 MyMethod를 호출하지 않습니다.
MyMethod
MyClass의 cctor가 완료되기 전에 같은 정적 메서드 를 호출 할 수 있습니까?
예. cctor가 cctor가 MyMethod를 호출하는 다른 유형을 사용하는 경우 MyClass cctor가 완료되기 전에 MyMethod가 호출됩니다.
어떤 cctor도 직접 또는 간접적으로 MyMethod를 호출하지 않습니다! 이제
MyMethod
MyClass의 cctor가 완료되기 전에 같은 정적 메서드 를 호출 할 수 있습니까?
아니.
여러 스레드가 관련된 경우에도 여전히 사실입니까?
예. cctor는 모든 스레드에서 정적 메소드를 호출하기 전에 하나의 스레드에서 완료됩니다.
cctor를 두 번 이상 호출 할 수 있습니까? 두 개의 스레드가 모두 cctor를 실행한다고 가정하십시오.
cctor는 얼마나 많은 스레드가 관련되어 있든 관계없이 최대 한 번 호출되도록 보장됩니다. 두 스레드가 MyMethod를 "동시에"호출하면 경쟁합니다. 그들 중 하나는 MyClass cctor가 우승 스레드에서 완료 될 때까지 레이스와 블록을 잃습니다.
cctor가 끝날 때까지 손실 스레드가 차단 됩니까? 정말 ?
정말.
그렇다면 승리 한 스레드 의 cctor가 이전에 손실 된 스레드가 가져온 잠금을 차단하는 코드를 호출하면 어떻게 될까요?
그런 다음 고전적인 잠금 순서 반전 조건이 있습니다. 프로그램 교착 상태. 영원히.
위험 해 보입니다. 교착 상태를 어떻게 피할 수 있습니까?
그렇게 할 때 아프면 그만두십시오 . cctor에서 차단할 수있는 일은 절대하지 마십시오.
복잡한 보안 요구 사항을 적용하기 위해 cctor 초기화 의미론에 의존하는 것이 좋은 생각입니까? 그리고 사용자 상호 작용을 수행하는 cctor를 갖는 것이 좋은 생각입니까?
좋은 아이디어도 아닙니다. 제 조언은 방법의 보안에 영향을 미치는 전제 조건이 충족되도록 다른 방법을 찾아야한다는 것입니다.
MSDN 에 따르면 정적 생성자 :
A static constructor is called automatically to initialize the class before the first instance is created or any static members are referenced.
So the static constructor will be called before the static method MyClass.MyMethod()
is invoked (assuming not also invoked during static construction or static field initialization of course).
Now, if you are doing anything asynchronous in that static constructor
, then it's your job to synchronize that.
The #3 is actually #1: static initialization does not start until the first use of the class to which it belongs.
It is possible if MyMethod
is called from the static constructor or a static initialization block. If you do not invoke MyMethod
directly or indirectly from your static constructor, you should be fine.
From the documentation (emphasis mine):
A static constructor is called automatically to initialize the class before the first instance is created or any static members are referenced.
You can guarantee 4 will always come after 2 (if you don't create a instance of your class from your static method), however the same is not true for 1 and 3.
The static constructor will be called before mymethod is executed. However if you are screwed if 4 is called before 2 then I suggest you re-think your design. Should not be doing complicated stuff in a static constructor anyway.
The CLR guarantees that the static constructor runs before any static members are accessed. However, your design is a bit smelly. It would be more straightforward to do something like this:
static void Main(string[] args)
{
bool userIsAuthenticated = MyClass.AuthenticateUser();
if (userIsAuthenticated)
MyClass.MyMethod();
}
With your design, if authentication fails, the only way to prevent MyMethod from running is by throwing an exception.
It's ensured that a static class's constructor has been called before any of its methods get executed. Example:
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:
Press enter
// after pressing enter
Hi incoming ...
Hi there!
Hi there!
Here's the actual order in which things go down:
- Start of
Main
- Start of the static
MyClass
constructor - End of the static
MyClass
constructor - Start of
MyMethod
- End of
Main
Or you could step through in the debugger.
참고URL : https://stackoverflow.com/questions/9398509/how-does-a-static-constructor-work
'programing' 카테고리의 다른 글
실행중인 프로그램에서 1 초간 기다리십시오. (0) | 2020.10.07 |
---|---|
Glide 라이브러리를 사용하여 이미지로드 완료시 표시되는 진행률 표시 줄의 가시성 설정 (0) | 2020.10.06 |
adb는 여러 파일을 가져옵니다. (0) | 2020.10.06 |
Java를 사용하여 디렉토리의 모든 파일을 재귀 적으로 나열 (0) | 2020.10.06 |
지정된 실행 파일 외부의 단일 단계 어셈블리 코드에 gdb를 사용하면 "현재 함수의 범위를 찾을 수 없습니다"오류가 발생합니다. (0) | 2020.10.06 |