연산자 오버로드 메서드
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 : 나중에 해서 블로그에 정리하자)
'언어 > C#' 카테고리의 다른 글
C# - @ (verbatim identifier) (2) | 2020.12.07 |
---|---|
C# 메서드 - 3. 확장 메서드 (1) | 2020.11.28 |
C# 메서드 - 1. 생성자 (0) | 2020.11.22 |
C# 의 타입 - 4. 객체의 식별 (Equals, GetHashCode) (1) | 2020.11.14 |
C# 의 타입 - 3. 값 타입과 참조타입 / 박싱, 언박싱 (4) | 2020.11.14 |