演算子のオーバーロード - 定義済みの単項演算子、算術演算子、等値演算子、および比較演算子

ユーザー定義型は定義済みの C# 演算子をオーバーロードできます。 つまり、1 つまたは両方のオペランドに該当する型では、演算のカスタム実装を提供できます。 オーバーロード可能な C# 演算子は、「オーバーロード可能な演算子」のセクションで示します。

演算子の宣言には operator キーワードを使用します。 演算子の宣言では、次の規則を満たす必要があります。

  • これには、publicstatic 修飾子の両方が含まれています。
  • 単項演算子には、1 つの入力パラメーターがあります。 2 項演算子には、2 つの入力パラメーターがあります。 どちらの場合も、少なくとも 1 つのパラメーターの型が T または T? でなければなりません。T は演算子の宣言が含まれる型です。

次の例は、有理数を表す簡略化された構造を定義しています。 構造体がいくつかの算術演算子をオーバーロードします。

public readonly struct Fraction
{
    private readonly int num;
    private readonly int den;

    public Fraction(int numerator, int denominator)
    {
        if (denominator == 0)
        {
            throw new ArgumentException("Denominator cannot be zero.", nameof(denominator));
        }
        num = numerator;
        den = denominator;
    }

    public static Fraction operator +(Fraction a) => a;
    public static Fraction operator -(Fraction a) => new Fraction(-a.num, a.den);

    public static Fraction operator +(Fraction a, Fraction b)
        => new Fraction(a.num * b.den + b.num * a.den, a.den * b.den);

    public static Fraction operator -(Fraction a, Fraction b)
        => a + (-b);

    public static Fraction operator *(Fraction a, Fraction b)
        => new Fraction(a.num * b.num, a.den * b.den);

    public static Fraction operator /(Fraction a, Fraction b)
    {
        if (b.num == 0)
        {
            throw new DivideByZeroException();
        }
        return new Fraction(a.num * b.den, a.den * b.num);
    }

    public override string ToString() => $"{num} / {den}";
}

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 への暗黙的な変換を定義することで、前の例を拡張できます。 その場合、オーバーロードされた演算子はこれら 2 つの型の引数をサポートします。 つまり、整数を分数に足し、結果として分数を取得できるようになります。

また、operator キーワードを使用してカスタムの型変換を定義することもできます。 詳細については、「ユーザー定義の変換演算子」 に関するページを参照してください。

オーバーロード可能な演算子

次の表は、オーバーロードできる演算子の一覧です:

演算子 メモ
+x, -x, !x, ~x, ++, --, true, false true 演算子と false 演算子は、一緒にオーバーロードする必要があります。
x + yx - yx * yx / yx % y
x & y, x | y, x ^ y,
x << yx >> yx >>> y
x == y, x != y, x < y, x > y, x <= y, x >= y ==!=<><=>= のペアでオーバーロードする必要があります。

オーバーロードできない演算子

次の表は、オーバーロードできない演算子を示しています:

演算子 代替
x && yx || y true 演算子と false 演算子の両方と & 演算子または | 演算子をオーバーロードします。 詳細については、「ユーザー定義の条件付き論理演算子」を参照してください。
a[i]a?[i] インデクサーを定義します。
(T)x キャスト式で実行できるカスタム型変換を定義します。 詳細については、「ユーザー定義の変換演算子」 に関するページを参照してください。
+=, -=, *=, /=, %=, &=, |=, ^=, <<=, >>=, >>>= 対応する 2 項演算子をオーバーロードします。 たとえば、二項演算子 + をオーバーロードすると、 += は暗黙的にオーバーロードされます。
^xx = yx.yx?.yc ? t : fx ?? y??= y
x..yx->y=>f(x)asawaitcheckeduncheckeddefaultdelegateisnameofnew
sizeof, stackalloc, switch, typeof, with
なし。

C# 言語仕様

詳細については、「C# 言語仕様」の次のセクションを参照してください。

関連項目