C#
최신 C# 기능
C# 11
C# 11 새기능
C# 11: Raw String Literal
C# 11: 문자열 내삽 복수라인
C# 11: u8 접미어
C# 11: Generic Math 지원
C# 11: Generic Attribute
C# 11: 리스트 패턴
C# 11: 파일 로컬 타입
C# 11: required modifier
C# 11: Auto-default struct
C# 11: ReadOnlySpan 패턴 매칭
C# 11: 확장된 nameof 범위
C# 11: nint, nuint
C# 11: ref 필드
C# 11: 소문자 타입명 경고
C# 11: 향상된 method group 변환
C# 10
VS 2022 설치
C# 10 global using
C# 10 File-scoped Namespace
C# 10 향상된 문자열 내삽
C# 10 향상된 람다식 유추
C# 10 struct 기능 향상
C# 10 record struct
C# 10 확장된 속성패턴
C# 10 향상된 명료한 할당
C# 10 Destructor 기능 개선
C# 9.0
C# 9 레코드 타입
C# 9 init accessor
C# 9 최상위 프로그램
C# 9 향상된 패턴 매칭
C# 9 향상된 Target Typing
C# 9 공변 리턴 타입
C# 9 Native Int 타입
C# 8.0
C# 8 디폴트 인터페이스 멤버
C# 8 패턴 매칭
C# 8 Nullable Reference Type
C# 8 인덱싱과 슬라이싱
C# 8 비동기 스트림
C# 8 using 선언
C# 8 널 병합 할당자
C# 8 구조체 읽기 전용 멤버
C# 8 기타 기능들
C# 7.0
C# 7.0 새기능
C# 7.0 패턴 매칭
C# 7.0 튜플
C# 7.0 로컬 함수
C# 7.0 out 파라미터
C# 7.0 리터럴 표현
C# 7.0 Deconstructor
C# 7.0 ref return
C# 7.0 async 리턴타입
C# 7.0 Expression-bodied
C# 7.0 throw expression
C# 6.0
C# 6.0 새기능
C# 6.0 널 조건 연산자
C# 6.0 문자열 내삽
C# 6.0 Dictionary초기자
C# 6.0 nameof 연산자
C# 6.0 using static문
C# 6.0 catch블럭 await
C# 6.0 Exception 필터
C# 6.0 자동 속성 초기자
C# 6.0 읽기전용 자동 속성
C# 6.0 Expression-bodied

C#으로 이해하는 자료구조
C# 프로그래밍 기초 실습 전자책
C# 8 : 디폴트 인터페이스 멤버 구현 (Default Inteface Members)

지금까지 (C# 8.0 이전) C#에서 인터페이스를 한번 배포한 후, 그 인터페이스를 수정하면 기존에 구현된 모든 타입들을 수정하지 않는 한 타입 오류를 발생시켰다. 더구나 그 인터페이스를 외부에서 사용한다면, 수정은 거의 불가능하였다. C# 8.0에서는 인터페이스에 새로운 멤버를 추가하고, 새로운 멤버의 Body 구현 부분을 추가할 수 있게 되었다. 이렇게 새로 추가된 인터페이스 멤버는 디폴트로 사용되기 때문에, 기존 구현된 타입들이 새 멤버를 추가적으로 구현되지 않을 경우, 이 디폴트 구현을 사용하게 된다.

예를 들어, ILogger 인터페이스가 초기에 아래와 같이 정의되었다고 가정하자.

예제

// ILogger v1.0
public interface ILogger
{
    void Log(string message);
}


이후 새로운 기능이 필요해서 ILogger 인터페이스에 2개의 메서드를 추가한 ILogger v2.0을 출시한다고 가정하자. 즉, ILogger v2.0은 Exception 객체를 받아이거나 로그타입을 추가적으로 받아들일 수 있도록 한 것이다. 이때, 새로 추가된 메서드들에 디폴트 메서드 Body부분을 구현해서 기존 v1.0을 사용하는 타입들도 별도의 수정없이 계속 사용할 수 있도록 한다.

예제

// ILogger v2.0
public interface ILogger
{
    void Log(string message);

    // 추가된 멤버들
    void Log(Exception ex) => Log(ex.Message);
    void Log(string logType, string msg)
    {
        if (logType == "Error" || 
            logType == "Warning" ||
            logType == "Info")
        {
            Log($"{logType}: {msg}");
        }
        else
        {
            throw new ApplicationException("Invalid LogType");
        }
    }
}


물론 ILogger v2.0을 새로 구현하는 클래스는 디폴트 멤버 구현을 사용하지 않고 자신만의 구현을 재정의할 수 있다.

예제

class MyLogger : ILogger
{
    public void Log(string message)
    {
        Console.WriteLine(message);
        Debug.WriteLine(message);
    }

    // 디폴트 구현을 사용하지 않고 새로 정의함
    public void Log(Exception ex)
    {
        Debug.WriteLine(ex.ToString());
    }
}


한가지 주의할 점은 인터페이스의 디폴트 멤버 구현을 엑세스하기 위해서는 인터페이스로 캐스팅된 변수를 사용한다는 점이다. 예를 들어, 위 ILogger.Log(string logType, string msg) 메서드에서 정의된 디폴트 구현은 MyLogger 객체에서 직접 엑세스할 수 없고, ILogger로 캐스팅 된 후에 엑세스할 수 있다.
Use Default Interface Member
본 웹사이트는 광고를 포함하고 있습니다. 광고 클릭에서 발생하는 수익금은 모두 웹사이트 서버의 유지 및 관리, 그리고 기술 콘텐츠 향상을 위해 쓰여집니다.