0Pricing
C# Academy · 강의

사용자 정의 변환

암시적 및 명시적 변환 연산자를 추가합니다.

사용자 정의 변환은(는) CoddyKit의 무료 C# Academy 강의입니다. 이것은 4개 중 3번째 강의입니다. 아래에서 전체 강의를 무료로 읽을 수 있으며, 내장 코드 에디터와 24/7 AI 튜터와 함께 브라우저에서 직접 실습할 수 있습니다. 이 강의는 C# Academy 학습 경로의 일부이며, 진행 상황이 웹과 CoddyKit 앱에 동기화됩니다. C# Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

사용자 정의 변환

C#에서는 implicit 및 explicit 연산자를 사용하여 형식이 다른 형식으로 변환되거나 다른 형식에서 변환되는 방식을 정의할 수 있습니다. 암시적 변환은 자동으로 수행되고, 명시적 변환에는 형 변환이 필요합니다.

암시적 변환

변환이 항상 안전하고 정보 손실이 없을 때 implicit operator를 사용하십시오. 컴파일러는 대상 형식이 필요한 모든 위치에서 이를 자동으로 적용합니다.

using System;

public struct Celsius
{
    public double Degrees;
    public Celsius(double d) { Degrees = d; }

    // Always safe: a Celsius is just a number
    public static implicit operator double(Celsius c) => c.Degrees;
}

public class Program
{
    public static void Main()
    {
        Celsius temp = new Celsius(21.5);
        double d = temp; // implicit, no cast needed
        Console.WriteLine(d);
    }
}

명시적 변환

변환 과정에서 정보가 손실되거나 실패할 수 있을 때 explicit operator를 사용하십시오. 호출자는 형 변환을 직접 작성해야 하며, 이를 통해 위험을 감수한다는 점을 명시합니다.

using System;

public struct Money
{
    public decimal Amount;
    public Money(decimal a) { Amount = a; }

    // Loses the fractional cents, so make it explicit
    public static explicit operator int(Money m) => (int)m.Amount;
}

public class Program
{
    public static void Main()
    {
        var m = new Money(19.99m);
        int dollars = (int)m; // explicit cast required
        Console.WriteLine(dollars);
    }
}

사용자 형식으로 변환

반대 방향의 변환도 정의할 수 있습니다. 즉 다른 형식에서 사용자 형식으로 변환하는 것입니다. 여기서는 implicit 연산자가 원시 double에서 Celsius를 만듭니다.

using System;

public struct Celsius
{
    public double Degrees;
    public Celsius(double d) { Degrees = d; }

    public static implicit operator Celsius(double d) => new Celsius(d);

    public override string ToString() => Degrees + "C";
}

public class Program
{
    public static void Main()
    {
        Celsius t = 18.0; // double implicitly becomes Celsius
        Console.WriteLine(t);
    }
}

암시적 변환과 명시적 변환: 선택하기

경험 법칙은 다음과 같습니다. 데이터가 절대 손실되지 않고 예외도 발생하지 않는 경우에만 암시적으로 만드십시오. 정밀도가 떨어지거나 오버플로가 발생하거나 실패할 수 있다면 명시적으로 만드십시오.

using System;

public struct Percentage
{
    public double Value; // 0..1
    public Percentage(double v) { Value = v; }

    // Safe and lossless -> implicit
    public static implicit operator double(Percentage p) => p.Value;
    // Could be out of range -> explicit
    public static explicit operator Percentage(double v) => new Percentage(v);
}

public class Program
{
    public static void Main()
    {
        double d = new Percentage(0.25);
        var p = (Percentage)0.5;
        Console.WriteLine(d + " " + p.Value);
    }
}

사용자 지정 형식 간 변환

변환은 기본 제공 형식에만 국한되지 않습니다. 예를 들어 극좌표에서 직교 좌표로 변환하는 것처럼, 직접 만든 두 형식 사이에서도 변환할 수 있습니다.

using System;

public struct Cartesian
{
    public double X, Y;
    public Cartesian(double x, double y) { X = x; Y = y; }
    public override string ToString() => "(" + Math.Round(X, 2) + ", " + Math.Round(Y, 2) + ")";
}

public struct Polar
{
    public double R, Theta;
    public Polar(double r, double theta) { R = r; Theta = theta; }
    public static explicit operator Cartesian(Polar p)
        => new Cartesian(p.R * Math.Cos(p.Theta), p.R * Math.Sin(p.Theta));
}

public class Program
{
    public static void Main()
    {
        var c = (Cartesian)new Polar(1.0, 0.0);
        Console.WriteLine(c);
    }
}

변환은 연산자와 결합됩니다

변환이 정의되면 값은 대상 형식의 식에 참여합니다. double로의 암시적 변환을 정의하면 해당 형식을 산술 연산에 직접 사용할 수 있습니다.

using System;

public struct Meters
{
    public double Value;
    public Meters(double v) { Value = v; }
    public static implicit operator double(Meters m) => m.Value;
}

public class Program
{
    public static void Main()
    {
        var distance = new Meters(5);
        double doubled = distance * 2; // uses implicit conversion to double
        Console.WriteLine(doubled);
    }
}

예상하기 어려운 암시적 변환 피하기

명백히 안전하지 않은 암시적 변환은 컴파일러가 조용히 적용하기 때문에 버그를 숨길 수 있습니다. 확신이 서지 않는다면 의도가 코드에 드러나도록 명시적 변환을 우선하십시오.

using System;

public struct UserId
{
    public int Value;
    public UserId(int v) { Value = v; }
    // Explicit on purpose: an int is not always a valid id
    public static explicit operator UserId(int v) => new UserId(v);
    public static explicit operator int(UserId id) => id.Value;
}

public class Program
{
    public static void Main()
    {
        var id = (UserId)42;
        int raw = (int)id;
        Console.WriteLine(raw);
    }
}

변환 연산자는 정적입니다

다른 연산자와 마찬가지로 변환 연산자는 public static입니다. 관련된 두 형식 중 정확히 하나는 해당 연산자를 선언하는 형식이어야 합니다.

using System;

public struct Fahrenheit
{
    public double Degrees;
    public Fahrenheit(double d) { Degrees = d; }
    public static implicit operator Fahrenheit(double d) => new Fahrenheit(d);
    public static implicit operator double(Fahrenheit f) => f.Degrees;
    public override string ToString() => Degrees + "F";
}

public class Program
{
    public static void Main()
    {
        Fahrenheit f = 98.6;
        double d = f;
        Console.WriteLine(f + " = " + d);
    }
}

실용적인 래퍼 형식

변환은 번거로움 없이 형식 시스템을 강화하는 얇은 래퍼 형식에서 특히 유용합니다. 여기서는 NonEmptyString을 string으로 암시적으로 변환할 수 있지만, 생성하려면 명시적 캐스트가 필요합니다.

using System;

public struct NonEmptyString
{
    public string Value;
    public NonEmptyString(string v)
    {
        if (string.IsNullOrEmpty(v)) throw new ArgumentException("empty");
        Value = v;
    }
    public static explicit operator NonEmptyString(string s) => new NonEmptyString(s);
    public static implicit operator string(NonEmptyString s) => s.Value;
}

public class Program
{
    public static void Main()
    {
        var name = (NonEmptyString)"Ada";
        string s = name;
        Console.WriteLine(s);
    }
}

직접 해 보기

안전한 암시적 외부 변환과 검증을 수행하는 명시적 내부 변환을 제공하는 래퍼를 정의하십시오. 어느 방향에서 캐스트가 필요한지 확인하십시오.

using System;

public struct Ratio
{
    public double Value;
    public Ratio(double v)
    {
        if (v < 0 || v > 1) throw new ArgumentOutOfRangeException(nameof(v));
        Value = v;
    }
    public static implicit operator double(Ratio r) => r.Value; // always safe
    public static explicit operator Ratio(double v) => new Ratio(v); // may throw
}

public class Program
{
    public static void Main()
    {
        var half = (Ratio)0.5;   // explicit, validated
        double d = half;          // implicit, safe
        Console.WriteLine(d * 100 + "%");
    }
}

빠른 확인

올바른 변환 종류를 선택하십시오.

복습

사용자 정의 변환을 사용하면 직접 만든 형식도 서로 원활하게 연동할 수 있습니다.

  • 항상 안전하고 손실이 없는 변환에는 implicit operator를 사용합니다.
  • 데이터가 손실되거나 변환이 실패할 수 있을 때는 explicit operator를 사용합니다.
  • 변환 대상은 기본 제공 형식이나 사용자 지정 형식일 수 있으며, 어느 방향으로든 변환할 수 있습니다.
  • 변환은 public static이며 관련된 형식 중 하나가 선언합니다.

자주 묻는 질문

“사용자 정의 변환” 강의는 무료인가요?

네 — “사용자 정의 변환” 전체 내용을 이 웹사이트에서 무료로 읽을 수 있습니다. 인터랙티브하게 실습하려면(내장 코드 에디터와 24/7 AI 튜터), CoddyKit PRO로 업그레이드하면 C# Academy 강의 전체를 잠금 해제할 수 있습니다. C# Academy 강의에는 총 4개의 강의가 포함되어 있습니다.

“사용자 정의 변환”에서 뭘 배우나요?

암시적 및 명시적 변환 연산자를 추가합니다. 브라우저에서 직접 실행하는 실습 코드로 C# Academy을(를) 배우며, 24/7 AI 튜터가 강의를 진행하면서 질문에 답변해줍니다.

C# Academy을(를) 시작하는 데 경험이 필요한가요?

사전 경험은 필요하지 않습니다. CoddyKit의 C# Academy은(는) 초급자부터 고급 학습자까지를 위해 구성되어 있으므로, 여기서 시작하거나 처음부터 시작할 수 있으며 자신의 속도대로 진행할 수 있습니다. 이것은 4개 중 3번째 강의입니다.

“사용자 정의 변환” 강의는 얼마나 걸리나요?

대부분의 CoddyKit 강의는 약 5~10분이 소요됩니다. 각 강의는 간결하고 인터랙티브하여 꾸준한 진행이 가능하며, 웹과 앱에서 중단한 부분부터 바로 시작할 수 있습니다.

이 C# Academy 강의에서 코드를 작성하고 실행할 수 있나요?

네. 모든 C# Academy 강의에는 내장 코드 에디터가 포함되어 있으므로, 브라우저에서 바로 실제 코드를 작성하고 실행한 후 즉시 AI 피드백을 받을 수 있습니다 — 로컬 설정이 필요 없습니다.

이 강의의 모든 강의

  1. 산술 연산자 오버로드
  2. 비교 연산자 오버로드
  3. 사용자 정의 변환
  4. 연산자 오버로드 모범 사례
← C# Academy(으)로 돌아가기