구조

구조체는 적은 양의 데이터와 간단한 동작이 있는 형식의 클래스보다 더 효율적일 수 있는 컴팩트 개체 형식입니다.

구문

[ attributes ]
type [accessibility-modifier] type-name =
    struct
        type-definition-elements-and-members
    end
// or
[ attributes ]
[<StructAttribute>]
type [accessibility-modifier] type-name =
    type-definition-elements-and-members

설명

구조체는 값 형식입니다. 즉, 스택에 직접 저장되거나 필드 또는 배열 요소로 사용될 때 부모 형식에서 인라인으로 저장됩니다. 클래스나 레코드와 달리 구조체는 pass-by-value 의미 체계를 포함합니다. 따라서 기본적으로 자주 액세스 및 복사하는 소규모 데이터 집계에 유용합니다.

위 구문에는 두 개의 폼이 표시되어 있습니다. 첫 번째는 간단한 구문은 아니지만 자주 사용됩니다. structend 키워드를 사용하는 경우 두 번째 구문에 나와 있는 StructAttribute 특성을 생략할 수 있기 때문입니다. 즉, StructAttributeStruct로 간략하게 작성할 수 있습니다.

이전 구문의 type-definition-elements-and-members멤버 선언 및 정의를 나타냅니다. 구조체는 생성자 및 변경 가능/불가능한 필드를 포함할 수 있으며 멤버 및 인터페이스 구현을 선언할 수 있습니다. 자세한 내용은 멤버를 참조하세요.

구조체는 상속에 참가할 수 없고, let 또는 do 바인딩을 포함할 수 없으며, 자신의 형식으로 된 필드를 재귀적으로 포함할 수 없습니다. 그러나 자신의 형식을 참조하는 참조 셀은 포함할 수 있습니다.

구조체는 let 바인딩을 허용하지 않으므로 구조체에서는 val 키워드를 사용하여 필드를 선언해야 합니다. val 키워드는 필드와 해당 형식을 정의하지만 초기화는 허용하지 않습니다. 대신 val 선언이 null 또는 0으로 초기화됩니다. 따라서 암시적 생성자(선언에서 구조체 이름 바로 뒤에 지정되는 매개 변수)를 포함하는 구조체에서는 val 선언을 DefaultValue 특성으로 주석 처리해야 합니다. 정의된 생성자가 있는 구조체도 0으로의 초기화를 지원합니다. 그러므로 DefaultValue 특성은 이러한 0 값이 필드에 유효함을 나타내는 선언입니다. 구조체의 암시적 생성자는 아무런 작업도 수행하지 않습니다. 해당 형식에 대해서는 letdo 바인딩이 허용되지 않지만 전달되는 암시적 생성자 매개 변수 값은 개인 필드로 사용할 수 있기 때문입니다.

명시적 생성자에서는 필드 값이 초기화될 수 있습니다. 명시적 생성자를 포함하는 구조체는 0으로의 초기화도 지원합니다. 그러나 DefaultValue 선언에서 val 특성을 사용하는 경우 명시적 생성자와 충돌하므로 해당 특성은 사용하지 않아야 합니다. 선언에 대한 val 자세한 내용은 명시적 필드: 키 val 워드를 참조하세요.

특성 및 액세스 가능성 한정자는 구조체에서 허용되며 다른 형식과 동일한 규칙을 따릅니다. 자세한 내용은 특성액세스 제어를 참조하세요.

다음 코드 예제에서는 구조체 정의를 보여 줍니다.

// In Point3D, three immutable values are defined.
// x, y, and z will be initialized to 0.0.
type Point3D =
    struct
        val x: float
        val y: float
        val z: float
    end

// In Point2D, two immutable values are defined.
// It also has a member which computes a distance between itself and another Point2D.
// Point2D has an explicit constructor.
// You can create zero-initialized instances of Point2D, or you can
// pass in arguments to initialize the values.
type Point2D =
    struct
        val X: float
        val Y: float
        new(x: float, y: float) = { X = x; Y = y }

        member this.GetDistanceFrom(p: Point2D) =
            let dX = (p.X - this.X) ** 2.0
            let dY = (p.Y - this.Y) ** 2.0

            dX + dY |> sqrt
    end

ByRefLike 구조체

유사 의미 체계를 준수할 수 있는 고유한 구조체를 정의할 byref수 있습니다. 자세한 내용은 Byrefs를 참조하세요. 이 작업은 특성으로 IsByRefLikeAttribute 수행됩니다.

open System
open System.Runtime.CompilerServices

[<IsByRefLike; Struct>]
type S(count1: Span<int>, count2: Span<int>) =
    member x.Count1 = count1
    member x.Count2 = count2

IsByRefLike 은 암시 Struct하지 않습니다. 둘 다 형식에 있어야 합니다.

F#의 "byref유사" 구조체는 스택 바인딩된 값 형식입니다. 관리되는 힙에는 할당되지 않습니다. byref-like 구조체는 수명 및 비 캡처에 대한 강력한 검사 집합으로 적용되므로 고성능 프로그래밍에 유용합니다. 규칙은 다음과 같습니다.

  • 함수 매개 변수, 메서드 매개 변수, 지역 변수, 메서드 반환으로 사용할 수 있습니다.
  • 클래스 또는 일반 구조체의 정적 또는 인스턴스 멤버일 수 없습니다.
  • 클로저 구문(async 메서드 또는 람다 식)으로 캡처할 수 없습니다.
  • 제네릭 매개 변수로 사용할 수 없습니다.

이러한 규칙은 사용량을 매우 강력하게 제한하지만 안전한 방식으로 고성능 컴퓨팅의 약속을 이행합니다.

ReadOnly 구조체

특성으로 구조체에 주석을 IsReadOnlyAttribute 달 수 있습니다. 예시:

[<IsReadOnly; Struct>]
type S(count1: int, count2: int) =
    member x.Count1 = count1
    member x.Count2 = count2

IsReadOnly 은 암시 Struct하지 않습니다. 구조체를 가지 IsReadOnly 려면 둘 다 추가해야 합니다.

이 특성을 사용하면 F# 및 C#에서 각각 처리할 inref<'T>in ref수 있는 메타데이터를 내보낸다.

읽기 전용 구조체 내에서 변경 가능한 값을 정의하면 오류가 발생합니다.

구조체 레코드 및 차별된 공용 구조체

레코드 및 구분된 공용 구조체를 특성이 있는 구조체로 나타낼 수 있습니다 [<Struct>]. 자세한 내용은 각 문서를 참조하세요.

참고 항목