다음을 통해 공유


캐스팅 및 변환(F#)

이 문서에서는 F#의 형식 변환에 대한 지원을 설명합니다.

산술 형식

F#은 정수와 부동 소수점 형식 간의 다양한 기본 형식 간의 산술 변환을 위한 변환 연산자를 제공합니다. 정수 계열 및 문자 변환 연산자에는 검사 및 un검사 형식이 있습니다. 부동 소수점 연산자와 enum 변환 연산자는 그렇지 않습니다. 검사 없는 양식이 정의 FSharp.Core.Operators 되고 검사 양식이 정의FSharp.Core.Operators.Checked됩니다. 검사 양식은 오버플로에 대해 검사 결과 값이 대상 형식의 제한을 초과하는 경우 런타임 예외를 생성합니다.

이러한 각 연산자의 이름은 대상 형식의 이름과 같습니다. 예를 들어 형식에 명시적으로 주석 byte 이 추가된 다음 코드에서는 두 가지 의미로 나타납니다. 첫 번째 항목은 형식이고 두 번째는 변환 연산자입니다.

let x : int = 5

let b : byte = byte x

다음 표에서는 F#에 정의된 변환 연산자를 보여줍니다.

Operator 설명
byte 부호 없는 8비트 형식인 바이트로 변환합니다.
sbyte 서명된 바이트로 변환합니다.
int16 부가된 16비트 정수로 변환합니다.
uint16 부호 없는 16비트 정수로 변환합니다.
int32, int 부가된 32비트 정수로 변환합니다.
uint32 부호 없는 32비트 정수로 변환합니다.
int64 부가된 64비트 정수로 변환합니다.
uint64 부호 없는 64비트 정수로 변환합니다.
nativeint 네이티브 정수로 변환합니다.
unativeint 부호 없는 네이티브 정수로 변환합니다.
float, double 64비트 배정밀도 IEEE 부동 소수점 숫자로 변환합니다.
float32, single 32비트 단정밀도 IEEE 부동 소수점 숫자로 변환합니다.
decimal 로 변환합니다 System.Decimal.
char 유니코드 문자로 System.Char변환합니다.
enum 열거형 형식으로 변환합니다.

기본 제공 기본 형식 외에도 이러한 연산자를 구현 op_Explicit 하는 형식 또는 op_Implicit 적절한 서명이 있는 메서드와 함께 사용할 수 있습니다. 예를 들어 변환 연산자는 형식을 int 매개 변수로 사용하고 반환하는 정적 메서드 op_Explicit 를 제공하는 모든 형식에서 작동합니다 int. 반환 형식으로 메서드를 오버로드할 수 없다는 일반적인 규칙에 대한 op_Explicit 특별한 예외로, 이 작업을 수행할 수 있습니다 op_Implicit.

열거형 형식

enum 연산자는 변환할 형식을 나타내는 enum 하나의 형식 매개 변수를 사용하는 제네릭 연산자입니다. 열거형 형식으로 변환할 때 형식 유추는 변환할 형식을 enum 확인하려고 시도합니다. 다음 예제에서 변수 col1 는 명시적으로 주석을 달지 않지만 해당 형식은 이후 같음 테스트에서 유추됩니다. 따라서 컴파일러는 열거형으로 변환하는 것을 추론할 Color 수 있습니다. 또는 다음 예제와 col2 같이 형식 주석을 제공할 수 있습니다.

type Color =
    | Red = 1
    | Green = 2
    | Blue = 3

// The target type of the conversion cannot be determined by type inference, so the type parameter must be explicit.
let col1 = enum<Color> 1

// The target type is supplied by a type annotation.
let col2 : Color = enum 2

다음 코드와 같이 대상 열거형 형식을 형식 매개 변수로 명시적으로 지정할 수도 있습니다.

let col3 = enum<Color> 3

열거형 캐스트는 열거형의 기본 형식이 변환되는 형식과 호환되는 경우에만 작동합니다. 다음 코드에서 변환은 간의 int32 불일치로 인해 컴파일에 실패합니다 uint32.

// Error: types are incompatible
let col4 : Color = enum 2u

자세한 내용은 열거형을 참조 하세요.

개체 형식 캐스팅

개체 계층 구조의 형식 간 변환은 개체 지향 프로그래밍의 기본 사항입니다. 변환에는 캐스팅(업캐스트) 및 캐스팅 다운(다운캐스팅)의 두 가지 기본 변환 유형이 있습니다. 계층 구조를 캐스팅한다는 것은 파생 개체 참조에서 기본 개체 참조로 캐스팅하는 것을 의미합니다. 이러한 캐스트는 기본 클래스가 파생 클래스의 상속 계층 구조에 있는 한 작동하도록 보장됩니다. 기본 개체 참조에서 파생 개체 참조로 계층 구조를 캐스팅하면 개체가 실제로 올바른 대상(파생) 형식의 인스턴스이거나 대상 형식에서 파생된 형식인 경우에만 성공합니다.

F#은 이러한 유형의 변환에 대한 연산자를 제공합니다. :> 연산자는 계층을 캐스팅하고:?>, 연산자는 계층을 캐스팅합니다.

업캐스팅

많은 개체 지향 언어에서 업캐스팅은 암시적입니다. F#에서 규칙은 약간 다릅니다. 개체 형식의 메서드에 인수를 전달하면 업캐스팅이 자동으로 적용됩니다. 그러나 모듈의 let-bound 함수의 경우 매개 변수 형식이 유연한 형식으로 선언되지 않는 한 업캐스팅은 자동으로 수행되지 않습니다. 자세한 내용은 유연한 형식을 참조 하세요.

:> 연산자는 정적 캐스트를 수행합니다. 즉, 캐스트의 성공이 컴파일 시간에 결정됩니다. 사용하는 :> 캐스트가 성공적으로 컴파일되면 유효한 캐스트이며 런타임에 실패할 가능성이 없습니다.

연산자를 upcast 사용하여 이러한 변환을 수행할 수도 있습니다. 다음 식은 계층 구조의 변환을 지정합니다.

upcast expression

업캐스트 연산자를 사용하는 경우 컴파일러는 컨텍스트에서 변환하는 형식을 유추하려고 시도합니다. 컴파일러가 대상 형식을 확인할 수 없는 경우 컴파일러는 오류를 보고합니다. 형식 주석이 필요할 수 있습니다.

다운캐스팅

연산자는 :?> 동적 캐스트를 수행합니다. 즉, 캐스트의 성공이 런타임에 결정됩니다. 연산자를 :?> 사용하는 캐스트는 컴파일 시간에 검사 않지만 런타임에 지정된 형식으로 캐스팅하려고 시도합니다. 개체가 대상 형식과 호환되면 캐스트가 성공합니다. 개체가 대상 형식과 호환되지 않으면 런타임 InvalidCastException에서 .

연산자를 downcast 사용하여 동적 형식 변환을 수행할 수도 있습니다. 다음 식은 계층 구조를 프로그램 컨텍스트에서 유추된 형식으로 변환하도록 지정합니다.

downcast expression

연산자에 관해서는 upcast 컴파일러가 컨텍스트에서 특정 대상 형식을 유추할 수 없는 경우 오류를 보고합니다. 형식 주석이 필요할 수 있습니다.

다음 코드에서는 및 :?> 연산자의 :> 사용을 보여 줍니다. 이 코드는 변환에 :?> 실패할 경우 throw되기 때문에 변환이 성공한다는 것을 알고 있을 때 연산자가 가장 잘 사용됨을 보여 줍니다 InvalidCastException . 변환이 성공할지 모르는 경우 예외를 생성하는 오버헤드를 방지하므로 식을 사용하는 match 형식 테스트가 더 좋습니다.

type Base1() =
    abstract member F : unit -> unit
    default u.F() =
     printfn "F Base1"

type Derived1() =
    inherit Base1()
    override u.F() =
      printfn "F Derived1"


let d1 : Derived1 = Derived1()

// Upcast to Base1.
let base1 = d1 :> Base1

// This might throw an exception, unless
// you are sure that base1 is really a Derived1 object, as
// is the case here.
let derived1 = base1 :?> Derived1

// If you cannot be sure that b1 is a Derived1 object,
// use a type test, as follows:
let downcastBase1 (b1 : Base1) =
   match b1 with
   | :? Derived1 as derived1 -> derived1.F()
   | _ -> ()

downcastBase1 base1

제네릭 연산 downcast 자와 upcast 형식 유추를 사용하여 인수 및 반환 형식을 결정하기 때문에 이전 코드 예제let base1: Base1 = upcast d1에서 .로 바꿀 let base1 = d1 :> Base1 수 있습니다.

자체에서 기본 클래스를 확인할 수 없으므로 upcast 형식 주석이 필요합니다.

암시적 업캐스트 변환

암시적 업캐스트는 다음과 같은 경우에 삽입됩니다.

  • 알려진 명명된 형식을 사용하여 함수 또는 메서드에 매개 변수를 제공하는 경우 여기에는 계산 식 또는 조각화와 같은 구문이 메서드 호출이 되는 경우가 포함됩니다.

  • 알려진 명명된 형식을 가진 레코드 필드 또는 속성에 할당하거나 변경할 때

  • 식의 if/then/else 분기에 다른 분기 또는 match 전체 알려진 형식에서 발생하는 알려진 대상 형식이 있는 경우

  • 목록, 배열 또는 시퀀스 식의 요소에 알려진 대상 형식이 있는 경우

예를 들어, 다음 코드를 고려하세요.

open System
open System.IO

let findInputSource () : TextReader =
    if DateTime.Now.DayOfWeek = DayOfWeek.Monday then
        // On Monday a TextReader
        Console.In
    else
        // On other days a StreamReader
        File.OpenText("path.txt")

여기서 조건부 분기는 각각 a TextReaderStreamReader 각각을 계산합니다. 두 번째 분기에서 알려진 대상 형식은 TextReader 메서드의 형식 주석과 첫 번째 분기에서 가져옵니다. 즉, 두 번째 분기에 업캐스트가 필요하지 않습니다.

추가 암시적 업캐스트가 사용되는 모든 지점에서 경고를 표시하려면 경고 3388(/warnon:3388 또는 속성 <WarnOn>3388</WarnOn>)을 사용하도록 설정할 수 있습니다.

암시적 숫자 변환

F#은 대부분의 경우 변환 연산자를 통해 숫자 형식의 명시적 확대를 사용합니다. 예를 들어 원본 또는 int16대상 형식을 알 수 없는 경우와 같은 int8 대부분의 숫자 형식에 float32float64대해 명시적 확대가 필요합니다.

그러나 암시적 업캐스트와 동일한 상황에서 64비트 정수로 확장된 32비트 정수에는 암시적 확대가 허용됩니다. 예를 들어 일반적인 API 셰이프를 고려합니다.

type Tensor(…) =
    static member Create(sizes: seq<int64>) = Tensor(…)

int64의 정수 리터럴을 사용할 수 있습니다.

Tensor.Create([100L; 10L; 10L])

또는 int32의 정수 리터럴:

Tensor.Create([int64 100; int64 10; int64 10])

형식 유추 중에 원본 형식과 double대상 형식을 모두 알 수 있는 경우 확대가 자동으로 nativeintint64int32int32 수행됩니다.int32 따라서 이전 예제 int32 와 같은 경우 리터럴을 사용할 수 있습니다.

Tensor.Create([100; 10; 10])

필요에 따라 경고 3389(/warnon:3389 또는 속성 <WarnOn>3389</WarnOn>)를 사용하도록 설정하여 암시적 숫자 확대가 사용되는 모든 지점에서 경고를 표시할 수도 있습니다.

. NET 스타일 암시적 변환

.NET API를 사용하면 정적 메서드의 op_Implicit 정의가 형식 간에 암시적 변환을 제공할 수 있습니다. 인수를 메서드에 전달할 때 F# 코드에서 자동으로 적용됩니다. 예를 들어 메서드를 명시적으로 호출 op_Implicit 하는 다음 코드를 고려합니다.

open System.Xml.Linq

let purchaseOrder = XElement.Load("PurchaseOrder.xml")
let partNos = purchaseOrder.Descendants(XName.op_Implicit "Item")

. 원본 식 및 대상 형식에 형식을 사용할 수 있는 경우 인수 식에 대해 NET 스타일 op_Implicit 변환이 자동으로 적용됩니다.

open System.Xml.Linq

let purchaseOrder = XElement.Load("PurchaseOrder.xml")
let partNos = purchaseOrder.Descendants("Item")

필요에 따라 경고 3395(/warnon:3395 또는 속성 <WarnOn>3395</WarnOn>)를 사용하도록 설정하여 모든 지점에서 경고를 표시할 수도 있습니다. NET 스타일 암시적 변환이 사용됩니다.

. 또한 NET 스타일 op_Implicit 변환은 암시적 업캐스트와 동일한 상황에서 메서드 인수가 아닌 식에도 자동으로 적용됩니다. 그러나 널리 또는 부적절하게 사용되는 경우 암시적 변환은 형식 유추와 제대로 상호 작용하지 못하고 이해하기 어려운 코드로 이어질 수 있습니다. 이러한 이유로 인수가 아닌 위치에서 사용할 때는 항상 경고를 생성합니다.

모든 지점에서 경고를 표시하려면 . NET 스타일 암시적 변환은 비 메서드 인수에 사용되며 경고 3391(/warnon:3391 또는 속성 <WarnOn>3391</WarnOn>)을 사용하도록 설정할 수 있습니다.

암시적 변환을 사용하기 위해 다음과 같은 선택적 경고가 제공됩니다.

  • /warnon:3388 (추가 암시적 업캐스트)
  • /warnon:3389 (암시적 숫자 확대)
  • /warnon:3391 (op_Implicit 메서드가 아닌 인수에서는 기본적으로 설정)
  • /warnon:3395 (op_Implicit at method 인수)

참고 항목