개발/C#

.Net Framework Guideline - Type Design(형식 디자인)-1

huiyu 2021. 8. 30. 19:44

형식 디자인 (Type Design) 지침

  • 클래스(Classes) : 참조 형식의 일반적인 경우. 대다수 프레임워크에서 사용하는 형식
  • 인터페이스(Interfaces) : 참조 형식과 형식 구현. 다중 상속을 시뮬레이션 있다.
  • 구조체(Structs) : 형식의 일반적인 경우, 단순 타입으로 사용
  • 열거형(enums) : 형식. 요일, 색상 간단한 세트를 정의하는데 사용
  • 정적 클래스(Static classes) : static member(정적 멤버) 컨테이너로 사용되는 형식.
  • 대리자(Delegates), 예외(Exceptions), 속성(Attributes), 배열(Array) :  모두 특정 용도로 사용되는 참조 형식,
    형식은 관련된 멤버가 세트가 이룰 있도록 구성할 것!

 

클래스와 구조체 간의 선택

모든 프레임워크 디자이너는 클래스(참조 형식)으로 디자인 할지, 구조체( 형식) 디자인할지 결정이 필요하다.

참조형식 vs 값형식

 참조 형식(reference types) 힙에 할당되고 가비지 컬렉트가 된다. 그러나 형식은 포함된 형식(containing types)에서 인라인(inline)이나 스택에 할당된다. 그리고 스택이 해제(unwinds)되거나 포함된 형식이 해제 같이 메모리에서 해제된다. 따라서 형식의 할당(allocations)이나 해제(deallocations) 일반적으로 비용이 저렴하다.

참조 형식 배열 vs 형식 배열

 참조 형식의 배열(array of reference types) 아웃 오브 라인(out-of-line)으로 할당된다. , 배열 요소는 힙에 있는 참조 형식의 인스턴스를 참조한다.
 값 형식의 배열(array of value types) 인라인(inline)으로 할당된다. , 배열 요소는 형식의 실제 인스턴스이다. 따라서 형식 배열의 할당이나 해제가 참조 형식 배열보다 저렴하며, 대부분 형식 배열이 참조 집약성(locality of reference) 훨씬 낮다.

메모리 사용

 값 형식은 참조 형식이나 인터페이스로 캐스팅 Boxing하며, 다시 캐스팅 할땐 Unboxing된다. Boxing 되면 힙에 할당 되고, 가비지 컬렉트 대상이 되는 개체이기 때문에 많은 Boxing Unboxing 성능에 부정적인 영향을 있다. 그러나 참조 형식이 캐스팅 이러한 Boxing 발생하지 않는다.

*Boxing&UnBoxing : https://docs.microsoft.com/ko-kr/dotnet/csharp/programming-guide/types/boxing-and-unboxing

할당

참조 형식 할당은 참조를 복사하는 반면 형식 할당은 전체 값을 복사한다. 따라서 대량 참조 형식의 할당이 대량 형식 할당보다 저렴하다.

전달

참조 형식은 참조로 전달되고, 형식은 값으로 전달 된다. 참조 형식의 인스턴스를 변경하면 인스턴스를 가리키는 모든 참조에 영향을 준다. 형식 인스턴스는 값으로 전달 복사되어 형식의 인스턴스를 변경하여도 복사본에 영향을 주지 않는다.

*일반적으로 프레임 워크에서 대부분 형식은 클래스를 사용해야 한다. 그러나 형식의 특성으로 인해 구조체를 사용하는 것이 적합한 경우도 있다.
 ->
일반적으로 작고, 수명이 짧은 경우라면 클래스보단 구조체를 사용하는 것이 좋다.

다음과 같은 경우엔 구조체로 정의한다.
 -
단일 값을 논리적으로 나타낸다 (int, double …)
 - 인스턴스 크기가 16바이트 미만이다.
 -
변할 없다(immutable)
 -
자주 Boxing하지 않는다.

외엔 클래스로 정의한다.

추상 클래스 (Abstract class) 디자인

- 추상 형식에선 public / protected internal 생성자를 선언하지 않는다
사용자가 형식(type) 인스턴스를 만들어야 하는 경우에만 생상자가 public이어야 한다. 추상 형식에서는 인스턴스를 만들 없기 때문에 public 생성자가 있는 추상 형식은 잘못 설계된 것이며 사용자가 오해할 있다.

- 추상 클래스(abstact class)에선 protected / internal 생성자를 정의한다.
protected
생성자는 일반적이며 하위 형식(subtype) 만들 기본 클래스(base class)에서 자체적으로 초기화 있도록 한다.
Internal 생성자는 추상 클래스의 구체적인 구현을 클래스를 정의하는 어셈블리로 제한하는데 사용할 있다.

- 제공되는 추상 클래스에서 상속되는 구체적인 형식(type) 하나 이상 제공해야 한다. System.IO.FileStream System.IO.Stream 구현한 객체이다. 이와 같이 구현한 코드를 하나 이상 함께 제공한다.

정적 클래스 (Static class) 디자인

 정적클래스는 정적 멤버만 포함하는 클래스로 정의된다.  C# 2.0이상에서는 정적 클래스는 봉인된 추상 클래스이며, 인스턴스 멤버는 재정의하거나 선언할  없다.
- 정적 클래스 사용을 자제할 .
  
정적 클래스는 프레임워크의 객체 지향 코어를 위해서만 사용해야한다.
- DO NOT treat static classes as a miscellaneous bucket.

- 정적 클래스에서 인스턴스 멤버를 선언하거나 재정의하지 않는다.
- 프래그래밍 언어에서 기본적으로 정적 클래스를 지원하지 않는다면, 정적 클래스를 봉인된 추상 클래스로 언언하고 private instance 생성자를 추가한다.

728x90
반응형