C# 11 の新機能を確認しています。目次は次の記事です。
rksoftware.hatenablog.com
今回は 「 ジェネリック型数値演算のサポート - ユーザー定義の checked 演算子 」。公式 Learn の記事は次です。
learn.microsoft.com
演算子のオーバーロードをする際に、checked 用の演算子を定義できます。
■ 確認
次のようなコードが書けます。
record struct Record(int Value) { public static Record operator +(Record arg1, Record arg2) => new(arg1.Value + arg2.Value); public static Record operator checked +(Record arg1, Record arg2) { checked { return new(arg1.Value + arg2.Value); } } }
ちなみにこのコードは .NET 6 を指定した場合は次のエラーになります。
エラー CS8936 機能 'チェックされたユーザー定義演算子' は C# 10.0 では使用できません。言語バージョン 11.0 以上を使用してください。
■ 実行
実行してみるとこんな感じで確かにそれぞれの +
演算子が使われます。
Console.WriteLine(new Record(100) + new Record(200)); // Record { Value = 1 } checked { Console.WriteLine(new Record(100) + new Record(200)); } // Record { Value = 2 } record struct Record(int Value) { public static Record operator +(Record arg1, Record arg2) => new(1); public static Record operator checked +(Record arg1, Record arg2) { checked { return new(2); } } }
■ checked の動作
checked の場合にオーバーフローを起こしてみましょう。例外がスローされます。
Console.WriteLine(new Record(int.MaxValue) + new Record(1)); // Record { Value = 1 } try { checked { Console.WriteLine(new Record(int.MaxValue) + new Record(1)); } } catch(Exception ex) { Console.WriteLine(ex.Message); } // Arithmetic operation resulted in an overflow. record struct Record(int Value) { public static Record operator +(Record arg1, Record arg2) => new(arg1.Value + arg2.Value); public static Record operator checked +(Record arg1, Record arg2) { checked { return new(arg1.Value + arg2.Value); } } }
今回は、int の checked 演算を行っているので、勝手に例外になってくれていますが、独自の計算をする場合は独自に例外をスローするようにしましょう。
※ オーバーフローで例外をスローしないなら checked 演算子にする必要がない
■ 覚えておきましょう
この機能は使わない人はほとんど使わない機能かもしれません。しかし他者が書いたコードでオーバーフロー時の挙動が不審な場合に出会うかもしれません。そんな時思い出して対策が行えるように覚えておきましょう。