目次

Ver. 11.0

※ 2022/5/4 現在、プレビュー版です。

リリース時期 2022/?
同世代技術
  • .NET 7.0
要約・目玉機能

執筆予定: C# 11.0 トラッキング issue

生文字列リテラル

C# 11 で、3つ以上の連続した " を使うことで、「一切エスケープが必要ない文字列リテラル」を書けるようになりました。

// """ から始まる文字列リテラル(raw string, 生文字列)。
var quote = """
    " はそのまま " として使われて、
    \ も \ のままの意味。
    \\ は \ が2個。
    {} とかも特別な解釈はされない。
    """;

この """ を使った書き方で、さらに文字列補間をすることもできます。

Console.WriteLine(format(123, "abc"));

static string format(int id, string name) => $$"""
    {
      "id": {{id /* ここは補間 */ }},
      "name": "{{name /* ここも補間 */}}"
    }
    """;

詳しくは「生文字列リテラル」で説明します。

Generic Math

前述のように いずれここより上で説明予定ですが、C# 11 / .NET 7 でインターフェイスの静的メンバーを仮想・抽象にできるようになります。

この機能の一番の用途は、数値型(intfloat など)に対するアルゴリズムをジェネリクスを使って書けるようにすることです。

これに伴って、数値型の演算子関連で3つ新機能が追加されています。

符号なし右シフト

符号付き整数(int とか sbyte とか)でも符号なし整数(uint とか byte とか)でも無関係に、 常に「符号なし右シフト(論理シフト)」をするための >>>演算子 (> の数が3つ)が追加されました。

using System.Numerics;

sbyte s = -1;

// ちゃんと符号なし右シフトに。
// FF → 7F → 3F → 1F → F → 7 → 3 → 1
for (int i = 0; i < 8; i++)
{
    Console.WriteLine($"{s:X}");
    s = LogicalRightShift(s, 1);
}

// >>> でどの型に対しても符号なし右シフト。
static T LogicalRightShift<T>(T s, int bits)
    where T : IShiftOperators<T,T>
    => s >>> bits;

詳しくは「【Generic Math】 C# 11 での演算子の新機能」で説明します。

checked 演算子オーバーロード

operator キーワードの後ろに checked を付けることで、 「checked 演算子」を定義できるようになりました。 これにより、ユーザー定義の演算子オーバーロードでも checked(オーバーフロー時に例外を投げる)と unchecked (オーバーフローしても例外を投げない)を切り替えられるようになります。

readonly struct Int2Bit
{
    public readonly byte Value;
    public Int2Bit(int value) => Value = (byte)(value & 0b11);
    public override string ToString() => Value.ToString();

    public static Int2Bit Checked(int value) => value is < 2 and >= 0 ? new(value) : throw new OverflowException();

    public static Int2Bit operator +(Int2Bit x, Int2Bit y) => new(x.Value + y.Value);
    public static Int2Bit operator checked +(Int2Bit x, Int2Bit y) => Checked(x.Value + y.Value);
}

詳しくは「【Generic Math】 C# 11 での演算子の新機能」で説明します。

シフト演算子の右オペランドの制限撤廃

(書きかけ)

その他

ジェネリックな属性

属性をジェネリック クラスにできるようになりました

// 属性クラスをジェネリックにできるように。
class TypeConverter<T> : Attribute { }

// <> で型引数を指定できる。
[TypeConverter<MyConverter>]
class MyClass { }

文字列補間中の改行

文字列補間で、以下のようなコードが書けるようになりました ({} の中で改行を入れれるようになりました)。

var a = 1;
var b = 2;
var s = $"a: {
    a // ここで改行できるのは C# 11 から
    }, b: {b}";

ちなみに、以下のように、$@ (文字列補間、かつ、逐語的文字列リテラル)を使う場合には C# 10.0 以前でも以下のようなコードが普通に書けました。

var a = 1;
var b = 2;
var s = $@"a: {
    a // $@ の場合は C# 10.0 以前でも OK
    }, b: {b}";

$"" の場合だけダメだった理由は今となっては思い出せない」というレベルだそうで、 仕様漏れ・バグ修正の類にギリギリの「新機能」になります。

更新履歴

ブログ