1 ポイント 投稿者 GN⁺ 2024-08-09 | 1件のコメント | WhatsAppで共有

要約

C#における型ユニオン(または判別共用体)を提案する文書。

動機

  • ソフトウェア開発では、変数に保存する値が常に同じ種類とは限らない。
  • たとえば、顧客とサプライヤーの定義が一部のプロパティだけを共有している場合、2つの型に対して類似した処理を行う必要があることがある。
  • 継承によって解決できるが、あらゆる状況に適しているわけではない。
  • C#では、限られた数の異なる型を同じ変数に保存できる方法が必要である。
  • 他の言語では、すでにこのような機能が提供されている。

解決策

  • C#でユニオン型を実装する最も適切な方法は、抽象基底クラスを用いた階層構造として考えることができる。
  • しかし、階層構造の制約や、無関係な型のユニオンを表現できないといった問題がある。
  • 複数種類のユニオンが必要になる可能性があり、この提案では4つのカテゴリに分類している。

標準 - ユニオンクラス

宣言

  • ユニオンクラスは enum に似た形で宣言される。
  • 各メンバーは状態変数を持つことができる。

生成

  • メンバー型のインスタンスを割り当てて生成される。

分解

  • 型テストとパターンマッチングによって分解される。

網羅性

  • すべてのメンバー型が switch 式または switch 文で考慮されていれば、デフォルトケースは不要である。

Null 許容性

  • 標準の Null 許容表記を使って Null を含めることができる。

実装

  • ユニオンクラスは抽象レコードクラスとして実装される。

特化 - ユニオン構造体

宣言

  • ユニオンクラスと似た形で宣言されるが、struct キーワードが追加される。

生成

  • メンバー型のインスタンスを割り当てて生成される。

分解

  • 型テストとパターンマッチングによって分解される。

網羅性

  • すべてのメンバー型が switch 式または switch 文で考慮されていれば、デフォルトケースは不要である。

Null 許容性

  • 標準の Null 許容表記を使って Null を含めることができる。

デフォルト値

  • ユニオン構造体は、未割り当てまたはデフォルト値が割り当てられた場合、未定義状態になる可能性がある。

実装

  • ユニオン構造体は構造体として実装され、メンバー型は入れ子のレコード構造体として実装される。

一時的 - 一時ユニオン

構文

  • 一時ユニオンは or パターン構文を使って参照される。

命名

  • ファイルまたはグローバル using エイリアスを使って、一時ユニオンに共通の名前を付けることができる。

生成

  • メンバー型のインスタンスを割り当てて生成される。

分解

  • 型テストとパターンマッチングによって分解される。

網羅性

  • すべてのメンバー型が switch 式または switch 文で考慮されていれば、デフォルトケースは不要である。

Null 許容性

  • 標準の Null 許容表記を使って Null を含めることができる。

相互交換性

  • 同一のメンバー型を持つ一時ユニオンは相互交換可能である。

ユーザー定義ユニオン

  • ユニオンクラスやユニオン構造体として指定できないユニオン型を宣言できる。
  • Closed 属性を使って階層構造を閉じることができる。
  • Union 属性を使って構造体ラッパーとして実装できる。

共通ユニオン

Option

  • 値が存在する場合も存在しない場合もあることを表す構造体ユニオンである。

Result

  • 関数から成功結果またはエラーを返す構造体ユニオンである。

関連提案

閉じた階層構造

  • Closed 属性を使って、抽象基底型に対して閉じたサブタイプ集合を宣言する。

シングルトン値

  • シングルトン属性を持つ型は、非型コンテキストで値として使用できる。

入れ子メンバー短縮記法

  • バインドされていない名前を使って、対象型の静的メンバーや入れ子型にバインドできる。

GN⁺の整理

  • この文書は C#における型ユニオンを提案しており、さまざまな状況で変数に複数の型を保存できる方法を提供する。
  • 他の言語ですでに提供されている機能を C#にも導入しようとする試みである。
  • 開発者がコードの可読性と保守性を高めるのに役立つ可能性がある。
  • 似た機能を提供する他言語の例としては F# がある。

1件のコメント

 
GN⁺ 2024-08-09
Hacker Newsのコメント
  • F#で判別共用体を使ってきたので、C#にもあるものだと思っていた

    • 現在はJavaを使っており、ADTのない言語に戻るのは難しいと感じている
    • C#の主要機能不足を弁明しなくて済むようになるのはうれしい
  • 「型ユニオン」という用語に馴染みがない

    • ML系言語のタグ付きユニオンに似ているように見える
    • C#開発者には既存の用語と違う名前を作る傾向があるのか気になる
  • 長年のC#開発者として、この提案のユースケースが明確ではないと感じる

    • 空のインターフェースとレコードクラスを宣言して実現できそうに見える
    • 何か見落としている点があるのか気になる
  • TypeScriptには型ユニオンがある

    • F#やHaskellの判別共用体に似ているように見える
    • 判別共用体には名前付きのケースコンストラクタがある
  • パターンマッチ可能なユニオンがないとプログラミングが難しくなる

    • 式問題の意味を完全には理解していなかった
    • 既存の多態性による拡張ポイントの提供は将来のクライアントに適しているかもしれない
    • チームが所有するコードにはパターンマッチ可能なユニオンのほうが適している
  • C#のユニオンでフィールドオフセットを使った経験がある

    • ポインタ/参照値と値のエイリアス化は未定義動作を引き起こす可能性がある
    • u64とオブジェクトの構造体ユニオンでは別個のフィールドが必要になり、8バイトを無駄にすることがある
  • 非公開コンストラクタとnugetパッケージを使って、スイッチ型で_ケースを不要にしている

    • 提案されている「ユニオンクラス」の糖衣構文を外した版に似ている
    • nugetパッケージが不要になり、構文糖が追加されるのはよい
  • ユニオン構造体が同時更新時のティアリングをどう扱うのかには触れられていない

    • ティアリングはメモリ安全性の問題を引き起こす可能性がある
    • 同じオフセットに整数フィールドと参照フィールドを持つバリアントがあり得る