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 : 구조체(struct) 읽기 전용 멤버

이전 C# 버전에서 구조체(struct) 전체를 readonly로 만들 수 있었는데, C# 8.0부터는 구조체의 각 멤버에 대해 개별적으로 readonly로 정의할 수 있게 되었다. 만약 구조체의 메서드나 속성이 구조체의 상태를 변경하지 않는다면 readonly로 적용할 수 있고, readonly 멤버가 다른 non-readonly 멤버를 엑세스하면 컴파일러가 Warning을 표시한다.



in 파라미터와 읽기 전용 멤버

C# 7.2에서 도입된 in 파라미터는 Value 타입의 파라미터를 Pass by reference로 전달할 수 있게 하는 기능을 제공한다. 만약 파라미터로 전달하는 구조체가(Value 타입) 큰 사이즈라면, Pass by value로 복사해서 전달하는 것보다 위치 정보만을 전달하는 Pass by reference를 사용하는 것이 성능면에서 효율적이다. 이러한 목적으로 in 파라미터는 구조체를 Pass by value로 전달할 수 있는 기능을 제공한다.

만약 구조체 전체가 readonly라면, 즉 구조체 내부의 모든 멤버가 readonly라면, in 파라미터를 사용하여 Pass by reference로 전달할 지라도 호출된 메서드(Callee)에서 구조체의 내부 상태를 변경하는 행위를 할 수 없으므로, 호출자(Caller)의 구조체는 변경되지 않을 것이 확실하다. 이러한 측면에 큰 사이즈의 구조체를 in 파라미터로 전달하기 위해, (가능하다면) 구조체를 readonly로 만들 것이 좋을 것이다. 하지만, 경우에 따라 구조체가 상태를 변경하는 멤버를 가질 수도 있다. 이러한 경우에는 일부 멤버들에 대해 readonly 멤버를 사용하는 것을 고려해 볼 수 있다.

Non-readonly 구조체인 경우 in 파라미터로 전달되면, 컴파일러는 호출된 메서드(Callee)에서 전달된 구조체의 멤버(메서드나 속성 등)을 호출할 때마다 구조체 파라미터를 복사하게 된다. 이는 컴파일러가 구조체의 멤버가 상태를 변경하는지 미리 알 수 없기 때문에, 방어적으로 구조체를 다시 복사(defensive copy or hidden copy)하여 사용하는 것이다. 구조체의 크기가 큰 경우 Callee 에서 그 구조체에 대해 10개의 메서드/속성을 호출한다면, 10번의 복사가 읽어나는데 이는 성능을 저하시키는 원인이 될 수 있다.

예를 들어, 아래 예제를 보면, Triangle 구조체가 정의되어 있고, 이 Triangle 인스턴스를 Check(in Triangle) 메서드에 in 파라미터로 전달하고 있다.

예제

public struct Triangle
{
    public int a, b, c;

    public Triangle(int a, int b, int c)
    {
        this.a = a;
        this.b = b;
        this.c = c;
    }

    public int Perimeter => a + b + c;
    public bool IsEquilateral => a == b && b == c;
}

private void Check(in Triangle tri)
{
    int perim = tri.Perimeter;
    bool equi = tri.IsEquilateral;

    Console.WriteLine($"{perim}, {equi}");
}

static void Main(string[] args)
{
    Triangle t = new Triangle(3, 4, 5);
    new Program().Check(t);
}


Check() 메서드에서 Triangle 구조체의 Perimeter와 IsEquilateral 멤버를 2번 호출하고 있는데, 이렇게 멤버를 호출할 때마다 직전에 Triangle 인스턴스를 로컬변수에 복사하게 된다. 아래 예제는 위 코드를 컴파일했을 때의 코드를 표현한 것으로 멤버 호출 직전에 구조체 파라미터를 복사하고 있다.

예제

private void Check([In] [IsReadOnly] ref Triangle tri)
{
    Triangle triangle = tri;
    int perimeter = triangle.Perimeter;
    triangle = tri;
    bool isEquilateral = triangle.IsEquilateral;
    Console.WriteLine(string.Format("{0}, {1}", perimeter, isEquilateral));
}

위와 같은 복사(hidden copy) 이슈를 해결하기 위해서, 만약 그 멤버가 구조체의 상태를 변화시키지 않을 경우 멤버 앞에 readonly를 붙여 컴파일러에게 hidden copy를 만들 필요가 없음을 알려 줄 수 있다. 즉, Perimeter와 IsEquilateral 멤버 앞에 아래와 같이 readonly를 표시할 수 있다.

예제

public readonly int Perimeter => a + b + c;
public readonly bool IsEquilateral => a == b && b == c;


Check() 메서드에서 readonly로 표시된 Perimeter와 IsEquilateral 멤버를 호출할 경우, 컴파일러는 아래와 같이 별도의 hidden copy를 필요로 하지 않는 코드를 그대로 만들게(emit) 된다.

예제

private void Check(in Triangle tri)
{
    int perim = tri.Perimeter;
    bool equi = tri.IsEquilateral;

    Console.WriteLine($"{perim}, {equi}");
}

본 웹사이트는 광고를 포함하고 있습니다. 광고 클릭에서 발생하는 수익금은 모두 웹사이트 서버의 유지 및 관리, 그리고 기술 콘텐츠 향상을 위해 쓰여집니다.




Comment nanenchanga2@*** 10/21/2020 8:50:04 AM
Comment admin@*** 10/22/2020 3:14:27 AM
Comment nanenchanga2@*** 10/22/2020 8:20:37 AM