[C#] Static을 알아보자

2022. 9. 30. 13:02C#/프로그래밍

static 한정자를 사용하여 특정 개체가 아니라 형식 자체에 속하는 정적 멤버를 선언할 수 있습니다. 

static 한정자를 사용하여 static 클래스를 선언할 수 있습니다.

클래스, 인터페이스 및 구조체에서

필드, 메서드, 속성, 연산자, 이벤트 및 생성자에 static 한정자를 추가할 수 있습니다. 

static 한정자는 인덱서 또는 종료자와 함께 사용할 수 없습니다.

 

클래스 인스턴스에는 클래스의 모든 인스턴스 필드에 대한 별도 복사본이 포함되지만

각 static 필드의 복사본은 한 개만 있습니다.

 

this를 사용하여 static 메서드 또는 속성 접근자를 참조할 수는 없습니다.

static 키워드가 클래스에 적용된 경우 클래스의 모든 구성원은 static이어야 합니다.

 

정적 클래스는 기본적으로 비정적 클래스와 동일하지만, 인스턴스화할 수 없다는 차이점이 있습니다.

즉, new 연산자를 사용하여 클래스 형식의 변수를 만들 수 없습니다.

인스턴스 변수가 없기 때문에 클래스 이름 자체를 사용하여 정적 클래스의 멤버에 액세스합니다. 

ex) Mp3.Play();

 

정적 메서드는 클래스 인스턴스가 아니라 클래스에 속해 있으므로

오버로드할 수 있지만 재정의할 수 없습니다.

 

필드를 static const로 선언할 수는 없지만, const 필드는 기본적으로 정적으로 동작합니다.

형식의 인스턴스가 아니라 형식에 속합니다.

따라서 정적 필드에 사용되는 것과 동일한 ClassName.MemberName 표기법을 사용하여 

const 필드에 액세스할 수 있습니다.  개체 인스턴스는 필요하지 않습니다.

 

 

정적  클래스의 주요 특징으로는

  1. 정적 멤버만 포함합니다.
  2. 인스턴스화할 수 없습니다.
  3. 봉인되어 있습니다.
  4. 인스턴스 생성자를 포함할 수 없습니다.

 

따라서 정적 클래스를 만드는 것은 기본적으로

정적 멤버와 private 생성자만 포함된 클래스를 만드는 것과 동일합니다.

private 생성자는 클래스가 인스턴스화되지 않도록 합니다.

정적 클래스를 사용하면 컴파일러에서 인스턴스 멤버가

실수로 추가되지 않도록 확인할 수 있다는 장점이 있습니다.

컴파일러는 이 클래스의 인스턴스를 만들 수 없도록 합니다.

정적 클래스는 봉인되므로 상속할 수 없습니다. 

Object를 제외하고 어떤 클래스에서도 상속할 수 없습니다.

정적 클래스는 인스턴스 생성자를 포함할 수 없습니다. 그러나 정적 생성자는 포함할 수 있습니다.

또한 클래스에 특수한 초기화가 필요한 정적 멤버가 포함된 경우

비정적 클래스에서 정적 생성자도 정의해야 합니다.

 

클래스, 인터페이스 및 static 클래스에 static 생성자가 있을 수 있습니다.

정적 생성자는 정적 데이터를 초기화하는 등 한 번만 수행해야 하는

특정 작업을 수행하는 데 사용됩니다.

 

프로그램이 시작되어 첫 번째 인스턴스가 만들어지거나

정적 멤버가 참조되기 전에 자동으로 static 생성자가 호출됩니다.

정적 생성자는 한 번만 호출되며, 프로그램이 있는 애플리케이션 도메인의 수명 동안 정적 클래스가 메모리에 유지됩니다.

 

정적 생성자에는 다음과 같은 속성이 있습니다.

  • 정적 생성자는 액세스 한정자를 사용하거나 매개 변수를 갖지 않습니다.
  • 클래스 또는 구조체에는 한 개의 정적 생성자만 사용할 수 있습니다.
  • 정적 생성자는 상속하거나 오버로드할 수 없습니다.
  • 정적 생성자는 직접 호출할 수 없으며, CLR(공용 언어 런타임)을 통해서만 호출할 수 있습니다. 자동으로 호출됩니다.
  • 사용자는 프로그램에서 정적 생성자가 실행되는 시기를 제어할 수 없습니다.
  • 정적 생성자는 자동으로 호출되며 첫 번째 인스턴스가 생성되거나 (기본 클래스가 아닌) 해당 클래스에서 선언된 정적 멤버가 참조되기 전에 클래스를 초기화합니다. 정적 생성자는 인스턴스 생성자보다 먼저 실행됩니다. 유형의 정적 생성자는 이벤트 또는 대리자에 할당된 정적 메서드가 호출될 때 호출되며 할당될 때는 호출되지 않습니다. 정적 필드 변수 이니셜라이저가 정적 생성자의 클래스에 있는 경우 클래스 선언에 나타나는 텍스트 순서대로 실행됩니다. 이니셜라이저는 정적 생성자가 실행되기 직전에 실행됩니다.
  • 정적 필드를 초기화하는 정적 생성자를 제공하지 않으면 모든 정적 필드가 C# 형식의 기본값에 나열된 기본값으로 초기화됩니다.
  • 정적 생성자가 예외를 throw하는 경우 런타임에서 생성자를 다시 호출하지 않으며 애플리케이션 도메인의 수명 동안 형식이 초기화되지 않은 상태로 유지됩니다. 가장 일반적으로, 정적 생성자가 형식을 인스턴스화할 수 없는 경우 또는 정적 생성자 내에서 발생하는 처리되지 않은 예외에 대해 TypeInitializationException 예외가 throw됩니다. 소스 코드에서 명시적으로 정의되지 않은 정적 생성자의 경우 문제 해결을 위해 IL(중간 언어) 코드를 검사해야 할 수 있습니다.
  • 정적 생성자가 있으면 BeforeFieldInit 형식 특성을 추가할 수 없습니다. 이 때문에 런타임 최적화가 제한됩니다.
  • static readonly로 선언된 필드는 해당 선언의 일부로 또는 정적 생성자에서만 할당할 수 있습니다. 명시적 정적 생성자가 필요하지 않은 경우 런타임 최적화 향상을 위해 정적 생성자를 통하지 않고 선언에서 정적 필드를 초기화합니다.
  • 런타임은 단일 애플리케이션 도메인에서 정적 생성자를 1번 이하로 호출합니다. 이 호출은 클래스의 특정 형식에 따라 잠긴 영역에서 수행됩니다. 정적 생성자의 본문에는 추가 잠금 메커니즘이 필요하지 않습니다. 교착 상태 위험을 방지하려면 정적 생성자와 이니셜라이저에서 현재 스레드를 차단하지 않습니다. 예를 들어 작업, 스레드, 대기 핸들 또는 이벤트를 기다리지 않고 잠금을 획득하지 않으며 병렬 루프, Parallel.Invoke, 병렬 LINQ 쿼리와 같은 병렬 작업 차단을 실행하지 않습니다.

 

Static의 단점

 

1. 전체 프로그램과 동일한 라이프 사이클

 

2. 정적 변수의 생성과 소멸을 개발자가 관여할 수 없음

 

3. 프로그램 전역에서 사용되므로 모든 스레드에서 어느 한 static 필드를 공유한다.

이 때 한 스레드에서 값을 변경할 경우 다른 모든 스레드가 영향을 받는다. (동시성 문제를 야기함)

위와 같은 이유로 스레드 안전성이 보장되지 않으며,  추가적인 안전 작업이 필요함.

 

4. static 메서드는 오버라이딩이 불가능함

 

5. static 멤버는 직렬화가 불가능함

객체 직렬화는 인스턴스에 대해 적용되기 때문에 클래스 자체 정보인 static 멤버는 포함되지 않는다.

 

 

 

Static 정리

 

static은 동일한 형식의 모든 클래스에서 공유하기 위한 멤버, 메서드를 선언하기 위해 사용한다.

 

개별 인스턴스가 아니라 형식 자체에 속하는 덕분에 인스턴스를 참조하지 않고 형식 이름만으로 접근할 수 있다.

 

또한 정적 선언된 변수는 해당 형식의 인스턴스가 얼마나 있든 상관없이 메모리에 하나만 존재한다.

 

정적 선언된 메서드는 객체 생성 없이 사용할 메서드가 있을 때, static 필드를 초기화시키고자 할 때

사용할 수 있다. (특정 클래스의 static 필드를 초기화시킬 때, static 메서드를 이용하면 굳이 객체 생성하여

정적 생성자를 실행시키지 않고도 클래스 이름과 .(점)연산자로 값을 바꿔줄 수 있다.)

 

static은 편리하지만, 객체지향의 캡슐화를 위반하고 스레드 동시성 문제를 야기할 수 있다.

또한 남발하면 메모리 낭비가 심하다는 단점도 있다.

 

 

'C# > 프로그래밍' 카테고리의 다른 글

편식소녀 뜯어보기 - Player,  (0) 2022.06.18
[C#] String Builder란?  (0) 2022.06.01
[C#] 필드란?  (0) 2022.05.30
[C#] 물음표의 의미  (0) 2022.05.30
[C#] Stream 이란?  (0) 2022.05.30