사용자 정의 형식은 미리 정의된 C# 연산자를 오버로드할 수 있습니다. 즉, 피연산자 중 하나 또는 둘 다 해당 형식인 경우 형식은 작업의 사용자 지정 구현을 제공할 수 있습니다. 오버로드 가능한 연산자 섹션에는 오버로드할 수 있는 C# 연산자가 표시됩니다.
키워드를 operator 사용하여 연산자를 선언합니다. 연산자 선언은 다음 규칙을 충족해야 합니다.
- 여기에는 한정자가
public포함됩니다. - 단항 연산자에는 하나의 입력 매개 변수가 있습니다. 이진 연산자에는 두 개의 입력 매개 변수가 있습니다. 각 경우에 하나 이상의 매개 변수는 형식
T또는T?이어야 하고, 연산자 선언이 포함된 형식은T입니다. - 한정자가 포함됩니다
static, 복합 할당 연산자와 같은+=를 제외하고. - 증가(
++) 및 감소(--) 연산자는 정적 또는 인스턴스 메서드로 구현할 수 있습니다. 인스턴스 메서드 연산자는 C# 14에 도입된 새로운 기능입니다.
다음 예제에서는 합리적인 숫자를 나타내는 간소화된 구조를 정의합니다. 구조체가 일부 산술 연산자를 오버로드합니다.
public struct Fraction
{
private int numerator;
private int denominator;
public Fraction(int numerator, int denominator)
{
if (denominator == 0)
{
throw new ArgumentException("Denominator cannot be zero.", nameof(denominator));
}
this.numerator = numerator;
this.denominator = denominator;
}
public static Fraction operator +(Fraction operand) => operand;
public static Fraction operator -(Fraction operand) => new Fraction(-operand.numerator, operand.denominator);
public static Fraction operator +(Fraction left, Fraction right)
=> new Fraction(left.numerator * right.denominator + right.numerator * left.denominator, left.denominator * right.denominator);
public static Fraction operator -(Fraction left, Fraction right)
=> left + (-right);
public static Fraction operator *(Fraction left, Fraction right)
=> new Fraction(left.numerator * right.numerator, left.denominator * right.denominator);
public static Fraction operator /(Fraction left, Fraction right)
{
if (right.numerator == 0)
{
throw new DivideByZeroException();
}
return new Fraction(left.numerator * right.denominator, left.denominator * right.numerator);
}
// Define increment and decrement to add 1/den, rather than 1/1.
public static Fraction operator ++(Fraction operand)
=> new Fraction(operand.numerator + 1, operand.denominator);
public static Fraction operator --(Fraction operand) =>
new Fraction(operand.numerator - 1, operand.denominator);
public override string ToString() => $"{numerator} / {denominator}";
// New operators allowed in C# 14:
public void operator +=(Fraction operand) =>
(numerator, denominator ) =
(
numerator * operand.denominator + operand.numerator * denominator,
denominator * operand.denominator
);
public void operator -=(Fraction operand) =>
(numerator, denominator) =
(
numerator * operand.denominator - operand.numerator * denominator,
denominator * operand.denominator
);
public void operator *=(Fraction operand) =>
(numerator, denominator) =
(
numerator * operand.numerator,
denominator * operand.denominator
);
public void operator /=(Fraction operand)
{
if (operand.numerator == 0)
{
throw new DivideByZeroException();
}
(numerator, denominator) =
(
numerator * operand.denominator,
denominator * operand.numerator
);
}
public void operator ++() => numerator++;
public void operator --() => numerator--;
}
public static class OperatorOverloading
{
public static void Main()
{
var a = new Fraction(5, 4);
var b = new Fraction(1, 2);
Console.WriteLine(-a); // output: -5 / 4
Console.WriteLine(a + b); // output: 14 / 8
Console.WriteLine(a - b); // output: 6 / 8
Console.WriteLine(a * b); // output: 5 / 8
Console.WriteLine(a / b); // output: 10 / 4
}
}
암시적 변환을 int에서 Fraction로 정의하여 앞의 예제를 확장할 수 있습니다. 그런 다음 오버로드된 연산자는 이러한 두 형식의 인수를 지원합니다. 즉, 분수에 정수를 추가하고 결과적으로 분수를 얻을 수 있습니다.
또한 키워드를 operator 사용하여 사용자 지정 형식 변환을 정의합니다. 자세한 내용은 사용자 정의 변환 연산자를 참조하세요.
오버로드가 가능한 연산자
다음 표에서는 오버로드할 수 있는 연산자를 보여줍니다.
| 운영자 | 비고 |
|---|---|
+x, -x, !x, ~x, ++, --, truefalse |
true 및 false 연산자를 함께 오버로드해야 합니다. |
x + y, x - y, x * y, x / y, x % yx & y, x | y, x ^ yx << y, , x >> yx >>> y |
|
x == y, x != y, x < y, x > y, x <= yx >= y |
다음과 같이 쌍으로 오버로드되어야 합니다: == 및 !=, < 및 >, <= 및 >=. |
+=, -=, *=, /=, %=, &=, \|=, ^=<<=, >>=>>>= |
복합 할당 연산자는 C# 14 이상에서 오버로드할 수 있습니다. |
복합 할당 오버로드된 연산자는 다음 규칙을 따라야 합니다.
- 한정자를
public포함해야 합니다. -
static수정자를 포함할 수 없습니다. - 반환 형식은 .이어야
void합니다. - 선언에는 복합 할당의 오른쪽을 나타내는 하나의 매개 변수가 포함되어야 합니다.
C# 14부터는 증가(++) 및 감소(--) 연산자를 인스턴스 멤버로 오버로드할 수 있습니다. 인스턴스 연산자는 새 인스턴스를 만들지 않도록 하여 성능을 향상시킬 수 있습니다. 인스턴스 연산자는 다음 규칙을 따라야 합니다.
- 한정자를
public포함해야 합니다. -
static수정자를 포함할 수 없습니다. - 반환 형식은 .이어야
void합니다. - 해당 매개 변수에 기본값이 있더라도 매개 변수를 선언할 수 없습니다.
오버로드할 수 없는 연산자
다음 표에서는 오버로드할 수 없는 연산자를 보여줍니다.
| 운영자 | 대안 |
|---|---|
x && y, x || y |
true 및 false 연산자와 & 또는 | 연산자를 모두 오버로드합니다. 자세한 내용은 사용자 정의 조건부 논리 연산자를 참조하세요. |
a[i], a?[i] |
인덱서 정의 |
(T)x |
캐스트 식에서 수행하는 사용자 지정 형식 변환을 정의합니다. 자세한 내용은 사용자 정의 변환 연산자를 참조하세요. |
^x, x = y, x.y, x?.y, c ? t : f, x ?? y, ??= yx..y, x->y, =>, f(x), as, await, checked, unchecked, default, delegate, is, nameof, new,sizeof, stackalloc, switch, typeofwith |
없음. |
C# 14 이전에는 복합 연산자를 오버로드할 수 없습니다. 해당 이진 연산자를 오버로드하면 해당 복합 할당 연산자가 암시적으로 오버로드됩니다.
연산자 오버로드 해결
중요합니다
이 섹션은 C# 14 이상에 적용됩니다. C# 14 이전에는 사용자 정의 복합 할당 연산자와 인스턴스 증가 및 감소 연산자가 허용되지 않습니다.
와 같은 x복합 할당 식에서 변수로 분류되는 경우 x «op»= y 인스턴스 연산자는 에 대한 «op»정적 연산자보다 선호됩니다. 오버로드된 «op»= 연산자가 형식 x 에 대해 선언되지 않았거나 x 변수로 분류되지 않은 경우 정적 연산자가 사용됩니다.
후위 연산++자에서 x이 변수로 분류되지 않거나 식을 사용하는 경우에는 인스턴스x++가 무시됩니다. 그렇지 않으면 인스턴스 operator ++에 우선권이 부여됩니다. 예를 들면 다음과 같습니다.
x++; // Instance operator++ preferred.
y = x++; // instance operator++ isn't considered.
이 규칙의 이유는 증가하기 전의 y 값에 x이 할당되어야 하기 때문입니다. 컴파일러는 참조 형식의 사용자 정의 구현에 대해 확인할 수 없습니다.
접두사 연산자 ++의 경우, x에서 ++x가 변수로 분류되는 경우 인스턴스 연산자가 정적 단항 연산자보다 더 선호됩니다.
C# 언어 사양
자세한 내용은 C# 언어 사양의 다음 섹션을 참조하세요.
참고하십시오
.NET