publicclassAnimal {
publicstring Name {
get;
set;
}
publicAnimal(): this("Dog") {}
publicAnimal(string name) {
Name = name;
}
}
var dog = new Animal(); // dog.Name 은 기본값인 "Dog" 으로 설정될 것이다.var cat = new Animal("Cat"); // cat.Name 은 "Cat" 으로 설정되며, 인자가 없는 생성자는 이때 호출되지 않는다.
publicclassSingletonClass
{
publicstatic SingletonClass Instance { get; } = new SingletonClass();
privateSingletonClass()
{
// 필요한 생성자 관련 코드를 이곳에 위치시킨다
}
}
위와 같은 패턴 사용 시, 생성자가 private 으로 선언되어 있으므로, SingletonClass 를 사용하는 코드에서 새로운 인스턴스를 임의로 생성할 수 없게 된다. SingletonClass 의 단일 인스턴스를 접근하기 위한 유일한 방법은 바로 SingletonClass.Instance static 속성을 사용하는 것이다.
이 Instance 속성은 C# 컴파일러가 자동 생성하는 static 생성자에 의해 할당된다. .NET 런타임은 이 static 생성자가 Instance 속성이 최초로 읽히기 전에 반드시 한번 실행됨을 보장해준다. 그러므로, 모든 동기화 및 초기화 관련 세부사항은 .NET 런타임에 의해 처리된다.
유의할 점은, 만약 static 생성자 실행이 실패할 경우, 이 Singleton 클래스는 해당 앱 도메인의 실행 기간 전체에 걸쳐 영구적으로 사용 불가능한 상태가 될 것이라는 점이다.
또한, 이 static 생성자는 Instance 에 대한 첫번째 접근시점에 맞추어 실행됨이 보장되는 것은 아니며, 그보다 더 빠른 시점에 불리게 될 것이다. 이는 초기화가 확정된 시점에 수행되지 않게됨을 의미한다. 실제적인 사례의 경우, JIT 는 보통 static 생성자를 Instance 에 대한 참조가 일어나는 메소드의 컴파일 시점 (실행 시점이 아닌) 에 호출하게 된다. 이는 성능 최적화를 위함이다.
static 생성자 (constructor) 는 해당 타입의 인스턴스가 최초로 초기화되거나, static 클래스 멤버나 static 메소드가 최초로 호출될 때 수행된다. static 생성자는 멀티스레드 환경에서도 안전하게 수행된다 (thread safe). static 생성자는 일반적으로 다음과 같은 경우에 사용된다:
static 한 상태를 초기화한다. 이 상태는 동일 클래스의 각기 다른 인스턴스간에 공유되는 상태값이다.
singleton 을 생성한다.
예제:
classAnimal {
// * static 생성자는 해당 클래스에// 최초로 접근할 때 단 한번 실행된다.// * static 생성자는 접근 한정자 (access modifier) 를 가질 수 없다.// * static 생성자는 파라미터를 가질 수 없다staticAnimal() {
Console.WriteLine("Animal initialized");
}
// 클래스의 인스턴스가 생성될 때마다 실행되는 instance 생성자.publicAnimal() {
Console.WriteLine("Animal created");
}
publicstaticvoidYawn() {
Console.WriteLine("Yawn!");
}
}
var turtle = new Animal();
var giraffe = new Animal();
Section 38.6: Nullable<T> 인자의 기반 (underlying) 타입에 대한 효과적인 사용법
모든 nullable 타입은 generic 타입이다. 또한 모든 nullable 타입은 값 (value) 타입이다.
역주: C# 8.0부터는 nullable reference 타입에 대한 새로운 개념이 추가되었습니다. Microsoft 문서 를 참조하세요.
Reflection 이나 코드 자동생성 목적의 코드를 작성할 때, Nullable.GetUnderlyingType 메소드의 결과를 효과적으로 사용할 수 있는 몇가지 기법을 아래의 코드에서 소개하고 있다:
publicstaticclassTypesHelper {
publicstaticboolIsNullable(this Type type) {
Type underlyingType;
return IsNullable(type, out underlyingType);
}
publicstaticboolIsNullable(this Type type, out Type underlyingType) {
underlyingType = Nullable.GetUnderlyingType(type);
return underlyingType != null;
}
publicstatic Type GetNullable(Type type) {
Type underlyingType;
return IsNullable(type, out underlyingType) ? type : NullableTypesCache.Get(type);
}
publicstaticboolIsExactOrNullable(this Type type, Func < Type, bool > predicate) {
Type underlyingType;
if (IsNullable(type, out underlyingType))
return IsExactOrNullable(underlyingType, predicate);
return predicate(type);
}
publicstaticbool IsExactOrNullable < T > (this Type type)
where T: struct {
return IsExactOrNullable(type, t => Equals(t, typeof (T)));
}
}
사용 예제:
Type type = typeof (int).GetNullable();
Console.WriteLine(type.ToString());
if (type.IsNullable())
Console.WriteLine("Type is nullable.");
Type underlyingType;
if (type.IsNullable(out underlyingType))
Console.WriteLine("The underlying type is " + underlyingType.Name + ".");
if (type.IsExactOrNullable < int > ())
Console.WriteLine("Type is either exact or nullable Int32.");
if (!type.IsExactOrNullable(t => t.IsEnum))
Console.WriteLine("Type is neither exact nor nullable enum.");
출력 결과:
System.Nullable`1[System.Int32]
Type is nullable.
The underlying type is Int32.
Type is either exact or nullable Int32.
Type is neither exact nor nullable enum.