与这个问题一样古老,我仍然对我上面的解释随机投票。解释仍然很好,但我将再次回答一个对我有用的类型作为联合类型的替代品(对 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
where a TA
or TP
,但Either
包含错误类型的值,您将收到运行时错误。
我通常在我希望方法返回结果或错误时使用它。它确实清理了该样式代码。我也非常偶尔(很少)使用它作为方法重载的替代品。实际上,对于这种过载来说,这是一个非常糟糕的替代品。