방프리

23.12.12 Chapter2. API 설계 (Item 23) 본문

C#/More Effective C#

23.12.12 Chapter2. API 설계 (Item 23)

방프리 2023. 12. 12. 00:03

Item 23 : 생성자, 변경자, 이벤트 핸들러를 위해 partial 클래스와 메서드를 제공하라

C#에서는 UI와 코드를 분리하기 위해서 partial이라는 키워드를 생성했다.
이로인해 디자이너와 개발자의 영역을 확실히 구분되었다. (각 부분에서 문제가 생기면 자기가 맡은 영역만 확인)
C# 3.0 버전에서는 기본 partial에서 새로운 기능을 추가하였는데 바로 partial 메서드이다.

간단히 설명하자면 기본 partial 클래스의 역할에서 조금 더 세분화되어 구현영역과 선언영역을 분리했다고 보면 
좋을 것 같다. (처음 예제를 보고 C++의 .h 와 .cpp 의 구조를 보는 듯 했다.)

대신 struct, class, interface와 달리 partial method를 선언할 때에는 약간의 제약이 필요하다.

1. abstract나 virtual이 될 수 없다.
2. 반환타입은 void로 고정이여야 한다.
3. 인터페이스 메서드를 구현할 수 없다.
4. out 매개변수를 초기화할 수 없으므로 out 매개변수를 사용할 수 없다.

위의 제약은 partial method가 선언만 하고 구현이 안되어도 상관없는 메서드이기 때문에 필수적으로 컴파일러가 인지해야
하는 상황일 때에는 만들 수 없다. 즉, partial로 선언하더라도 구현부가 없다면 실행하지 않고 컴파일러는 해당 선언부를 
그냥 뛰어넘는다.

public partial class GneratedStuff
{
    private struct ReportChange
    {
        public readonly int OldValue;
        public readonly int NewValue;
        
        public ReportChange(int oldValue, int newValue)
        {
            OldValue = oldValue;
            NewValue = newValue;
        }
    }
    
    private class RequestChange
    {
        public ReportChange Values { get; set; }
        public bool Cancel { get; set; }
    }
    
    partial void ReportValueChanging(RequestChange args);
    partial void ReportValueChanged(RequestChange values);
    
    public void UpdateValue(int newValue)
    {
        RequestChange updateArgs = new RequestChange
        {
            Values = new ReportChange(storage, newValue),
        };
        
        ReportValueChanging(updateArgs);
        if (!updateArgs.Cancel)
        {
            storage = newValue;
            ReportValueChanged(new ReportChange(storage, newValue));
        }
    }
}
Comments