다음을 통해 공유


ref 구조체 형식(C# 참조)

구조체 형식 선언에 ref 한정자를 사용할 수 있습니다. ref struct 형식의 인스턴스는 스택에 할당되며 관리되는 힙으로 이스케이프할 수 없습니다. 이를 위해 컴파일러는 다음과 같이 ref struct 형식의 사용을 제한합니다.

  • ref struct는 배열의 요소 형식일 수 없습니다.
  • ref struct는 클래스의 필드 또는 비 ref struct의 선언된 형식일 수 없습니다.
  • ref structSystem.ValueType 또는 System.Object에 boxing할 수 없습니다.
  • 람다 식 또는 로컬 함수에서 ref struct 변수를 캡처할 수 없습니다.
  • C# 13 ref struct 이전에는 메서드에서 변수를 async 사용할 수 없습니다. C# 13부터 ref struct 변수는 async 메서드의 await 식과 동일한 블록에서 사용할 수 없습니다. 그러나 동기 메서드에서는 ref struct 변수(예: Task 또는 Task<TResult>를 반환하는 메서드)를 사용할 수 있습니다.
  • C# 13 이전에는 반복기에서 ref struct 변수를 사용할 수 없습니다. C# 13부터 yield return 문이 있는 코드 세그먼트에 없는 경우 ref struct 형식 및 ref 로컬을 반복기에서 사용할 수 있습니다.
  • C# 13 이전에는 ref struct이(가) 인터페이스를 구현할 수 없습니다. C# 13부터 ref 구조체는 인터페이스를 구현할 수 있지만 ref 안전 규칙을 준수해야 합니다. 예를 들어 boxing 변환이 필요하기 때문에 ref struct 형식을 인터페이스 형식으로 변환할 수 없습니다.
  • C# 13 이전에는 ref struct이(가) 형식 인수가 될 수 없습니다. C# 13부터 ref struct 형식 매개 변수가 where 절에 allows ref struct을(를) 지정할 때 형식 인수가 될 수 있습니다.

일반적으로 ref struct 형식의 데이터 멤버도 포함하는 형식이 필요한 경우 ref struct 형식을 정의합니다.

public ref struct CustomRef
{
    public bool IsValid;
    public Span<int> Inputs;
    public Span<int> Outputs;
}

ref structreadonly로 선언하려면 형식 선언에서 readonlyref 한정자를 결합합니다(readonly 한정자는 ref 한정자 앞에 와야 함).

public readonly ref struct ConversionRequest
{
    public ConversionRequest(double rate, ReadOnlySpan<double> values)
    {
        Rate = rate;
        Values = values;
    }

    public double Rate { get; }
    public ReadOnlySpan<double> Values { get; }
}

.NET에서 ref struct의 예는 System.Span<T>System.ReadOnlySpan<T>입니다.

ref 필드

C# 11부터 다음 예제와 같이 ref 필드를 ref struct에 선언할 수 있습니다.

public ref struct RefFieldExample
{
    private ref int number;

    public int GetNumber()
    {
        if (System.Runtime.CompilerServices.Unsafe.IsNullRef(ref number))
        {
            throw new InvalidOperationException("The number ref field is not initialized.");
        }

        return number;
    }
}

ref 필드에는 null 값이 있을 수 있습니다. Unsafe.IsNullRef<T>(T) 메서드를 사용하여 ref 필드가 null인지 확인합니다.

다음과 같은 방법으로 readonly 한정자를 ref 필드에 적용할 수 있습니다.

  • readonly ref: 생성자 또는 init 접근자 내에서만 = ref 연산자를 사용하여 이러한 필드를 ref 다시 할당할 수 있습니다. 필드 액세스 한정자가 허용하는 모든 지점에서 = 연산자를 사용하여 값을 할당할 수 있습니다.
  • ref readonly: 어떤 경우에도 = 연산자를 사용하여 이러한 필드에 값을 할당할 수 없습니다. 그러나 = ref 연산자를 사용하여 필드를 ref 다시 할당할 수 있습니다.
  • readonly ref readonly: 생성자 또는 init 접근자에서만 이러한 필드를 ref 다시 할당할 수 있습니다. 어떤 경우에도 필드에 값을 할당할 수 없습니다.

컴파일러는 ref 필드에 저장된 참조가 참조보다 오래 되지 않도록 합니다.

ref 필드 기능을 사용하면 System.Span<T>와(과) 같은 형식을 안전하게 구현할 수 있습니다.

public readonly ref struct Span<T>
{
    internal readonly ref T _reference;
    private readonly int _length;

    // Omitted for brevity...
}

Span<T> 형식은 메모리의 연속 요소에 액세스하는 참조를 저장합니다. 참조를 사용하면 Span<T> 인스턴스가 참조하는 스토리지를 복사하지 않도록 할 수 있습니다.

삭제 가능한 패턴

삭제 가능한 ref struct를 정의할 수 있습니다. 이렇게 하려면 ref struct삭제 가능 패턴에 맞는지 확인해야 합니다. 즉 이 구조체에는 액세스 가능하고 매개 변수가 없으며 void 반환 형식을 갖는 인스턴스 Dispose 메서드가 있습니다. using 문 또는 선언을 일회용 ref struct의 인스턴스와 함께 사용할 수 있습니다.

C# 13부터는 ref struct 형식에서 IDisposable을(를) 구현할 수도 있습니다. 그러나 오버로드 확인은 인터페이스 메서드보다 삭제 가능한 패턴을 선호합니다. 컴파일러는 적절한 Dispose 메서드를 IDisposable.Dispose 찾을 수 없는 경우에만 메서드로 확인됩니다.

인터페이스를 구현하는 ref struct 형식에 대한 제한 사항

이러한 제한은 인터페이스를 구현하는 ref struct 형식이 필요한 ref 안전 규칙을 준수하도록 합니다.

  • ref struct은(는) 자신이 구현하는 인터페이스의 인스턴스로 변환될 수 없습니다. 이 제한에는 매개 변수가 인터페이스 형식인 경우 ref struct 형식을 인수로 사용할 때의 암묵적 변환이 포함됩니다. 이 변환은 ref 안전을 위반하는 boxing 변환으로 이어집니다.
  • 인터페이스 를 구현하는 ref struct는 모든 인터페이스 멤버를 구현해야 합니다. ref struct는 인터페이스에 기본 구현이 포함된 멤버를 구현해야 합니다.

컴파일러는 이러한 제한을 적용합니다. 인터페이스를 구현하는 ref struct 형식을 작성하는 경우 새 업데이트마다 새 기본 인터페이스 멤버가 포함될 수 있습니다. 이러한 새 메서드에 대한 구현을 제공할 때까지 애플리케이션은 컴파일되지 않습니다.

Important

인터페이스를 구현하는 ref struct은(는) 나중에 소스 호환성이 손상되고 이진 호환성이 손상되는 변경이 발생할 가능성이 있습니다. ref struct이(가) 다른 어셈블리에 정의된 인터페이스를 구현하고 해당 어셈블리가 해당 인터페이스에 기본 멤버를 추가하는 업데이트를 제공하는 경우 중단이 발생합니다.

소스 중단은 ref struct이(가) 다시 컴파일할 때 발생합니다. 기본 구현이 있더라도 새 멤버를 구현해야 합니다.

이진 중단은 ref struct 형식 다시 컴파일하지 않고 외부 어셈블리를 업그레이드하고 업데이트된 코드가 새 메서드의 기본 구현을 호출하는 경우 발생합니다. 런타임은 기본 멤버가 액세스할 때 예외를 throw합니다.

C# 언어 사양

자세한 내용은 C# 언어 사양의 다음 섹션을 참조하세요.

ref 필드에 대한 자세한 내용은 하위 수준 구조체 개선 제안 노트를 참조하세요.

참고 항목