연산자 오버로딩
연산자 오버로딩은 메소드 오버로딩과 비슷하다. 사실, 연산자 오버로딩은 메소드 오버로딩의 한 유형이다. 연산자를 오버로딩할 때 두가지 중요한 제약이 있다. 하나는 연산자의 우선순위를 변경할 수 없다는 것이고 다른 하나는 연산자의 피연산자수를 변경할 수 없다는 것이다. 연산자 오버로딩 형식은 아래와 같다.
public static result-type operator unary-operator ( op-type operand )
public static result-type operator binary-operator (op-type operand,
op-type2 operand2 )
첫 번째는 단항 연산자를 오버로딩하는 형식이고 두 번째는 이항 연산자를 오버로딩하는 형식이다. 형식을 보면 알겠지만 C++에서의 연산자 오버로딩과 차이가 있다. 중요한 차이점은 C++에서는 연산자 오버로딩을 클래스의 일반 멤버함수처럼 취급하지만 C#에서는 정적 메소드로 취급한다. 이러한 차이점 때문에 피연산자의 수가 다르게 된다. 즉, C++에서는 이항연산자인 경우 피연산자는 하나만 주어지는 형태로 오버로딩 된다. 주어지지 않는 나머지 피연산자는 this 객체를 나타낸다.
모든 연산자가 다 오버로딩 가능한 것은 아니다. 오버로딩 가능한 단항 연산자에는 +, -, !, ~, ++, --, true, false가 있으며 이항 연산자에는 + - * / % & | ^ << >> == != > < >= <= 가 있다. 이 중 ++, -- 연산자는 prefix 형태로만 오버로딩 가능하다. =, &&, ||, ?:, new 는 오버로딩 할 수 없다. 복합 연산자인 *=, /=, +=, -= %=, &=, |=, ^=, >>=, <<=도 오버로딩 할 수 없다. 관계 연산자 (<와 >, <=와 >=, ==와 !=)는 쌍으로 오버로딩 하여야 한다. 둘 중 하나만 오버로딩 하여서는 안된다. 그리고 ==와 !=를 오버로딩할 경우는 Object 클래스에서 상속받은 Equals 메소드를 재정의 하여야 하며 Equals 메소드를 재정의 할 경우는 GetHashCode 메소드도 같이 재정의 하여야 한다.
C#에서는 조건식이 반드시 불리안 형이어야 한다. 따라서 아래처럼 객체 자체를 조건식에 사용하고자 할 경우에는 true, false 연산자를 오버로딩하여야 한다.
if (a) { ...}
Time 클래스에 대한 + 연산자를 오버로딩한 예는 아래와 같다. 정적 메소드로 선언하였으며 두개의 Time 형의 객체를 인수로 받는 것으로 정의되어 있다.
public static Time operator+(Time t1, Time t2)
{
int newHours = t1.hours + t2.hours;
int newMinutes = t1.minutes + t2.minutes;
return new Time(newHours, newMinutes);
}