C# 11 の新機能を確認しています。目次は次の記事です。
rksoftware.hatenablog.com
今回は 「 ジェネリック型数値演算のサポート - 緩和されたシフト演算子 」。公式 Learn の記事は次です。
learn.microsoft.com
シフト演算子のオーバーロードをする際に、右オペランド (第 2 引数) に int でない型を使えます。
■ 確認
次のようなコードが書けます。
Console.WriteLine(new Sample() >> new Dummy()); // Sample { } record struct Dummy { } record struct Sample { public static Sample operator >>(Sample arg1, Dummy arg2) => new Sample(); }
ちなみにこのコードは .NET 6 を指定した場合は次のエラーになります。
エラー CS8936 機能 '緩和されたシフト演算子' は C# 10.0 では使用できません。言語バージョン 11.0 以上を使用してください。
record struct Dummy { } record struct Sample { public static Sample operator >>(Sample arg1, Dummy arg2) => new Sample(); // エラー CS8936 機能 '緩和されたシフト演算子' は C# 10.0 では使用できません。言語バージョン 11.0 以上を使用してください。 }
これまでは、int だけだったので、>>
の右は int と int に暗黙的な型変換のできる型しか書けませんでした。次のような感じです。
Console.WriteLine(4 >> 1); // 2 Console.WriteLine(4 >> (short)1); // 2
record struct Sample { public static Sample operator >>(Sample arg1, int arg2) => new Sample(); }
■ どういうこと
次のように、数値計算した結果が int でなくとも右に書けるシフト演算が定義できます。
Console.WriteLine(new Sample() >> 1.0 / 2.0); record struct Sample { public static Sample operator >>(Sample arg1, int arg2) => new Sample(); public static Sample operator >>(Sample arg1, double arg2) => new Sample(); }
これは、自分で算術演算を実装した型を使うときに利便を想定しているみたいです。具体例としては System.Numerics.INumber<TSelf> を実装した型などを想定しているようです。
Console.WriteLine(new Sample() >> new RNumber()); record struct Sample { public static Sample operator >>(Sample arg1, RNumber arg2) => new Sample(); } record struct RNumber : System.Numerics.INumber<RNumber> { // 実装コード省略
今までは、シフト演算の右に独自の型を書くならば、暗黙的な型変換を実装する必要がありました。これからはその必要がなくなります。
Console.WriteLine(new Sample() >> new RNumber()); record struct Sample { public static Sample operator >>(Sample arg1, int arg2) => new Sample(); } record struct RNumber(int Value) { public static implicit operator int(RNumber arg) => arg.Value; }
■ 覚えておきましょう
この機能は使わない人はほとんど使わない機能かもしれません。しかし他者が書いたコードでオーバーフロー時の挙動が不審な場合に出会うかもしれません。そんな時思い出して対策が行えるように覚えておきましょう。