คำถามเก่าเท่านี้ฉันยังคงได้รับคะแนนโหวตแบบสุ่มจากคำอธิบายข้างต้น คำอธิบายยังคงใช้ได้ดีเหมือนเดิม แต่ฉันจะตอบเป็นครั้งที่สองด้วยประเภทที่ให้บริการฉันเป็นอย่างดีและใช้แทนประเภทสหภาพ (คำตอบที่พิมพ์อย่างชัดเจนสำหรับคำถามที่ 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.Primary;
        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);
}
var fishBotOrConcreteMixer = DemoFunc(new JumpRope());
var fishBotOrConcreteMixer = DemoFunc(new PiCalculator());
หมายเหตุสำคัญ:
- คุณจะได้รับข้อผิดพลาดรันไทม์หากคุณไม่ตรวจสอบIsPrimaryก่อน
- คุณสามารถตรวจสอบใด ๆหรือIsNeitherIsPrimaryIsAlternate
- คุณสามารถเข้าถึงค่าผ่านPrimaryและAlternate
- มีตัวแปลงโดยนัยระหว่าง TP / TA และอย่างใดอย่างหนึ่งเพื่อให้คุณส่งผ่านค่าหรือที่Eitherใดก็ได้ที่คาดหวัง ถ้าคุณทำผ่านEitherที่TAหรือTPคาดว่า แต่Eitherมีผิดประเภทของค่าที่คุณจะได้รับข้อผิดพลาด runtime
ฉันมักจะใช้สิ่งนี้ในที่ที่ฉันต้องการวิธีการส่งคืนผลลัพธ์หรือข้อผิดพลาด มันทำความสะอาดโค้ดสไตล์นั้นจริงๆ ฉันยังเป็นครั้งคราว ( ไม่ค่อย ) ใช้นี้แทน overloads วิธีการ ตามความเป็นจริงนี่เป็นการทดแทนที่แย่มากสำหรับการโอเวอร์โหลด