언어/C#

C# 메서드 - 2. 연산자 오버로드 메서드

tsyang 2020. 11. 28. 18:37

연산자 오버로드 메서드


CLR 사양에 따르면 연산자 오버로드 메서드는 반드시 public이면서 static이어야 한다.

또한 C#을 포함한 많은 언어들이 연산자 메서드의 매개변수는 반드시 연산자 메서드가 정의된 타입과 같은 타입이어야 한다는 조건도 포함되어있다. 이렇게 하는 이유는 컴파일러가 적절한 시간 내에 가능한 연산자 메서드를 찾아 쉽게 연결할 수 있도록 하기 위함이다.

 

연산자 오버로드는 다음과 같이 사용할 수 있다.

 

public sealed class MyClass
{
    public static MyClass operator - (MyClass a, MyClass b) 
    { return new MyClass(); } // 이항 연산자 -
    public static MyClass operator - (MyClass a) 
    { return new MyClass(); } // 단항 연산자 -
}

 

변환 연산자 메서드 


위와 같은 연산자 뿐만 아니라 객체간의 타입을 변환해야 하는 경우에도 연산자를 오버로드하여 쓸 수 있다.

 

이경우 암시적 변환과 명시적 변환 모두 재정의 할 수 있으며, 다음과 같이 한다.

 

public sealed class Rational // 유리수 클래스
{
    public int numerator, denominator;  // 분자, 분모

    public static implicit operator float(Rational r)
    {
        return r.numerator / r.denominator;
    }

    public static explicit operator int(Rational r)
    {
        return r.numerator / r.denominator;
    }

    public static implicit operator Rational(int intVal)
    {
        return new Rational(){ numerator = intVal, denominator = 1 };
    }
}

public sealed class Program
{
    public static void Main()
    {
        Rational a = new Rational();

        int val = a; // 오류 : 암시적으로 'Rational' 형식을 'int' 형식으로 변환할 수 없습니다.
        int val2 = (int)a; // OK

        float fval = a; //OK
        float fval2 = (float)a; //OK

        Rational b = 3; //OK
        Rational b2 = (Rational) 3; //OK
    }
}

implicit 으로 정의된 변환 연산자 메서드는 암묵적, 명시적 형식을 지원하며 explicit으로 정의한 변환 연산자는 오로지 명시적인 캐스팅만 지원한다.

 

내부적으로 본다면, C# 컴파일러는 코드에서 발생하는 캐스팅을 감지하여 Rational 타입에 의하여 정의된 변환 연산자 메서드를 호출하는 IL 코드를 만들어낸다. 이 때 메서드의 이름을 알아내는 법은 Rational 타입의 메타데이터를 참고한다. 

 

참고로 암묵적 변환 연산자는 변환으로 인해 자릿수나 정밀도에 손상을 주지 않는 변환인것이 좋다. 정밀도에 손상이 간다면 명시적 형 변환만을 허용하는게 좋다. 

 

연산자 오버로드와 메서드와 변환 연산자 메서드를 좀 더 정확히 이해하려면 System.Decimal 타입을 롤 모델로 보고 분석하면 좋다. ( TODO : 나중에 해서 블로그에 정리하자)