C # 멤버 변수 초기화; 모범 사례?
선언시 클래스 멤버 변수를 초기화하는 것이 더 낫습니까?
private List<Thing> _things = new List<Thing>();
private int _arb = 99;
또는 기본 생성자에서?
private List<Thing> _things;
private int _arb;
public TheClass()
{
_things = new List<Thing>();
_arb = 99;
}
단순히 스타일의 문제입니까, 아니면 성능 상충 관계가 있습니까?
성능면에서 실제 차이는 없습니다. 필드 이니셜 라이저는 생성자 논리로 구현됩니다. 유일한 차이점은 필드 이니셜 라이저가 "base"/ "this"생성자보다 먼저 발생한다는 것입니다.
생성자 접근 방식은 자동 구현 속성과 함께 사용할 수 있습니다 (필드 이니셜 라이저는 사용할 수 없음).
[DefaultValue("")]
public string Foo {get;set;}
public Bar() { // ctor
Foo = "";
}
그 외에는 필드 이니셜 라이저 구문을 선호하는 경향이 있습니다. 나는 그것이 지역화 된 것을 유지한다는 것을 알았습니다.
private readonly List<SomeClass> items = new List<SomeClass>();
public List<SomeClass> Items {get {return items;}}
할당 된 위치를 찾기 위해 위아래로 사냥을 갈 필요가 없습니다.
명백한 예외는 복잡한 논리를 수행하거나 생성자 매개 변수를 처리해야하는 경우입니다.이 경우 생성자 기반 초기화가 적합합니다. 마찬가지로 생성자가 여러 개인 경우 필드가 항상 동일한 방식으로 설정되는 것이 바람직하므로 다음과 같은 ctor가있을 수 있습니다.
public Bar() : this("") {}
public Bar(string foo) {Foo = foo;}
편집 : 사이드 코멘트로서, 위의 필드 이니셜 라이저가있는 다른 필드 (표시되지 않음)가있는 경우 호출하는 생성자 ( base(...)
예 : public Bar(string foo)
ctor) 에서만 직접 초기화됩니다 . 다른 생성자는 ctor에 의해 수행된다는 것을 알고 있기 때문에 필드 이니셜 라이저를 실행 하지 않습니다this(...)
.
실제로 설명하는 필드 이니셜 라이저는 편리한 속기입니다. 컴파일러는 실제로 유형에 대해 정의한 각 인스턴스 생성자의 시작 부분에 초기화 코드를 복사합니다.
여기에는 두 가지 의미가 있습니다. 첫째, 모든 필드 초기화 코드가 각 생성자에 복제되고, 둘째, 생성자에 포함하여 필드를 특정 값으로 초기화하는 코드는 실제로 필드를 다시 할당합니다.
따라서 성능 측면에서 컴파일 된 코드 크기와 관련하여 필드 이니셜 라이저를 생성자로 이동하는 것이 좋습니다.
반면에 성능에 미치는 영향과 코드 '팽창'은 일반적으로 무시할 수 있으며 필드 이니셜 라이저 구문은 생성자 중 하나에서 일부 필드를 초기화하는 것을 잊을 수있는 위험을 줄이는 중요한 이점이 있습니다.
필드 이니셜 라이저의 한 가지 주요 제한 사항은 try-finally 블록으로 래핑 할 방법이 없다는 것입니다. 필드 이니셜 라이저에서 예외가 발생하면 이전 이니셜 라이저에서 할당 된 모든 리소스가 중단됩니다. 그것을 막을 방법이 없습니다. 보호 된 기본 생성자가 참조로 IDisposable을 받아들이도록하고 그 자체를 첫 번째 작업으로 가리킴으로써 어색하게 구성의 다른 오류를 처리 할 수 있습니다. 그런 다음 예외가 발생한 경우 부분적으로 생성 된 개체에 대해 Dispose를 호출하는 팩토리 메서드를 제외하고 생성자 호출을 피할 수 있습니다. 이 보호 기능은 새 개체에 대한 참조를 "밀수"한 후 주 클래스 생성자가 실패하는 경우 파생 클래스 이니셜 라이저에서 생성 된 IDisposable을 정리할 수 있도록합니다. 불행히도
필드 이니셜 라이저를 사용하거나 Init () 함수를 만듭니다. 생성자에 이러한 것들을 넣는 문제는 두 번째 생성자를 추가해야하는 경우 코드 복사 / 붙여 넣기로 끝납니다 (또는이를 간과하고 초기화되지 않은 변수로 끝남).
선언 된 곳에서 초기화합니다. 또는 생성자가 Init () 함수를 호출하도록합니다.
인스턴스 변수의 경우 주로 스타일의 문제입니다 (생성자를 사용하는 것을 선호합니다). 정적 변수의 경우 인라인 초기화에 성능상의 이점 이 있습니다 (물론 항상 가능한 것은 아닙니다).
정말 당신에게 달려 있습니다.
나는 종종 그것들을 인라인으로 초기화한다. 왜냐하면 나는 생성자가 정말로 필요하지 않을 때 생성자를 갖는 것을 좋아하지 않기 때문이다 (나는 작은 클래스를 좋아한다!).
On added point to the above - You always have a constructor when implementing classes that have an implementation. If you do not declare one then the default instructor is inferred by the compiler [public Foo(){}]; a constructor that takes no arguments.
Often times I like to offer both approaches. Allow constructors for those that wish to use them and allow the Field Initializers for situations where you wish to use a simplified or default implementation of your class / type. This adds flexibility to your code. Keep in mind that anyone can use the default field initializer if they choose ... be sure to declare it manually if you offer more than one constructor - public Foo(){}
참고URL : https://stackoverflow.com/questions/298183/c-sharp-member-variable-initialization-best-practice
'program tip' 카테고리의 다른 글
Javascript가 포함 된 HTML 파일을 편집하기 위해 emacs를 어떻게 구성합니까? (0) | 2020.09.04 |
---|---|
65 개 요소로 구성된 배열을 선언하는 것보다 1000 배 빠른 64 개 요소로 여러 배열을 선언합니다. (0) | 2020.09.04 |
PHP 메모리 프로파일 링 (0) | 2020.09.04 |
클래스 다이어그램을 만들기위한 도구 (0) | 2020.09.04 |
사용하지 않는 함수 매개 변수 값을 void로 캐스팅하는 이유는 무엇입니까? (0) | 2020.09.04 |