この質問と同じくらい古いので、私はまだ上記の私の説明にランダムな賛成票を受け取ります。説明はそのままでも完全に問題ありませんが、共用体型の代わりとして役立つ型(C#で直接サポートされていない質問に対する強い型の回答)でもう一度答えます。 )。
using System;
using System.Diagnostics;
namespace Union {
[DebuggerDisplay("{currType}: {ToString()}")]
public struct Either<TP, TA> {
enum CurrType {
Neither = 0,
Primary,
Alternate,
}
private readonly CurrType currType;
private readonly TP primary;
private readonly TA alternate;
public bool IsNeither => currType == CurrType.Neither;
public bool IsPrimary => currType == CurrType.Primary;
public bool IsAlternate => currType == CurrType.Alternate;
public static implicit operator Either<TP, TA>(TP val) => new Either<TP, TA>(val);
public static implicit operator Either<TP, TA>(TA val) => new Either<TP, TA>(val);
public static implicit operator TP(Either<TP, TA> @this) => @this.Primary;
public static implicit operator TA(Either<TP, TA> @this) => @this.Alternate;
public override string ToString() {
string description = IsNeither ? "" :
$": {(IsPrimary ? typeof(TP).Name : typeof(TA).Name)}";
return $"{currType.ToString("")}{description}";
}
public Either(TP val) {
currType = CurrType.Primary;
primary = val;
alternate = default(TA);
}
public Either(TA val) {
currType = CurrType.Alternate;
alternate = val;
primary = default(TP);
}
public TP Primary {
get {
Validate(CurrType.Primary);
return primary;
}
}
public TA Alternate {
get {
Validate(CurrType.Alternate);
return alternate;
}
}
private void Validate(CurrType desiredType) {
if (desiredType != currType) {
throw new InvalidOperationException($"Attempting to get {desiredType} when {currType} is set");
}
}
}
}
上記のクラスは、TPまたはTAのいずれかであるタイプを表します。あなたはそれをそのように使うことができます(タイプは私の元の答えを参照しています):
// ...
public static Either<FishingBot, ConcreteMixer> DemoFunc(Either<JumpRope, PiCalculator> arg) {
if (arg.IsPrimary) {
return new FishingBot(arg.Primary);
}
return new ConcreteMixer(arg.Secondary);
}
// elsewhere:
var fishBotOrConcreteMixer = DemoFunc(new JumpRope());
var fishBotOrConcreteMixer = DemoFunc(new PiCalculator());
重要な注意事項:
IsPrimary
最初にチェックしないと、ランタイムエラーが発生します。
IsNeither
IsPrimary
またはのいずれかを確認できますIsAlternate
。
Primary
とを介して値にアクセスできますAlternate
- TP /TAとEither<TP、TA>の間には暗黙のコンバーターがあり、値または
Either
期待される場所に値を渡すことができます。またはが期待される場所を渡したが、に間違ったタイプの値が含まれている場合、実行時エラーが発生します。Either
TA
TP
Either
私は通常、メソッドが結果またはエラーのいずれかを返すようにしたい場合にこれを使用します。それは本当にそのスタイルコードをクリーンアップします。また、非常にまれに(めったに)これをメソッドのオーバーロードの代わりに使用します。現実的には、これはそのような過負荷の非常に貧弱な代替手段です。