注意這個人似乎並沒有要求一個Tuple(一種持有c類型struct但沒有名字的幾種類型的類型),而是一個Tagged Union/Sum type。
一個元組有一種類型,一個帶標籤的聯合只有一個值爲2或更多的類型。
他給出的例子是一個haxe枚舉,它不像c#枚舉(基本上是一個數字的名字)。
從http://haxe.org/ref/enums
注: HAXE枚舉的行爲非常相似標籤聯合,使一個給定的方法結果的每一個「案例」的規範和捕獲。由於所有Enum狀態必須在switch語句中指定,因此這對於完全定義給定方法的行爲以及確保處理這些行爲非常有用。
如果您想確保每個案件總是處理不要在下面的類中實現單個Action Run方法。
你也可能希望避免的名字無論是作爲(左/右)經常使用專門的錯誤或結果的工會(以左爲錯誤或正確的是結果。
這裏是一個2成員工會的一個實現。
您還可能要爲3,4,5成員工會的這個副本具有相同的名稱
public sealed class Union<A,B,C> : IEquatable<Union<A,B>>
public sealed class Union<A,B,C,D> : IEquatable<Union<A,B,C,D>>
public sealed class Union<A,B,C,D,E> : IEquatable<Union<A,B,C,D,E>>
下一個格局
[Serializable()]
public sealed class Union<A,B> : IEquatable<Union<A,B>>
{
private enum TypeTag{ A, B};
private Union()
{
}
private A AValue;
private B BValue;
private TypeTag tag;
public static Union<A,B> CreateA (A a)
{
var u = new Union<A,B>();
u.AValue = a;
u.tag = TypeTag.A;
return u;
}
public static Union<A,B> CreateB (B b)
{
var u = new Union<A,B>();
u.BValue = b;
u.tag = TypeTag.B;
return u;
}
public U SelectOn<U> (Func<A, U> withA, Func<B, U> withB)
{
if (withA == null)
throw new ArgumentNullException ("withA");
if (withB == null)
throw new ArgumentNullException ("withB");
if (tag == TypeTag.A)
{
return withA (AValue);
}
else if (tag == TypeTag.B)
{
return withB (BValue);
}
throw new InvalidOperationException ("Unreachable code.");
}
public void Run (Action<A> actionIfA, Action<B> actionIfB)
{
if (actionIfA == null)
throw new ArgumentNullException ("actionIfA");
if (actionIfB == null)
throw new ArgumentNullException ("actionIfB");
if (tag == TypeTag.A)
{
actionIfA (AValue);
}
else if (tag == TypeTag.B)
{
actionIfB (BValue);
}
}
public void Run (Action<A> actionIfA)
{
if (actionIfA == null)
throw new ArgumentNullException ("actionIfA");
if (tag == TypeTag.A)
{
actionIfA (AValue);
}
}
public void Run (Action<B> actionIfB)
{
if (actionIfB == null)
throw new ArgumentNullException ("actionIfB");
if (tag == TypeTag.B) {
actionIfB (BValue);
}
}
public override string ToString()
{
if (tag == TypeTag.A)
{
return "Type A" + typeof(A).ToString() + ": " + AValue.ToString();
}
else if (tag == TypeTag.B) {
return "Type B" + typeof(B).ToString() + ": " + BValue.ToString();
}
throw new InvalidOperationException ("Unreachable code.");
}
public override int GetHashCode()
{
unchecked
{
int result = tag.GetHashCode();
if (tag == TypeTag.A) {
result = (result * 397)^(AValue != null ? AValue.GetHashCode() : 0);
} else if (tag == TypeTag.B) {
result = (result * 397)^(BValue != null ? BValue.GetHashCode() : 0);
}
return result;
}
}
public override bool Equals (object other)
{
if (other is Union<A,B>)
{
return this.Equals((Union<A,B>)other);
}
return false;
}
public bool Equals (Union<A,B> other)
{
if (this.tag != other.tag)
{
return false;
}
if (tag == TypeTag.A)
{
return this.AValue.Equals(other.AValue);
}
else if (tag == TypeTag.B)
{
return this.AValue.Equals(other.AValue);
}
return false;
}
}
用法示例:
var i = Union<int,string>.CreateA(5);
var s = Union<int,string>.CreateB("Fre");
s.Run(actionIfA: n => { Console.WriteLine("1.number*3 is " + n*3); },
actionIfB: str => { Console.WriteLine("1.uppercase string is " + str.ToUpper()); });
var r = i.SelectOn(withA: n => "2.number*3 is" + n*3 , withB: str=> "2.uppercase string is" + str.ToUpper());
Console.WriteLine(r);
s.Run(actionIfA: n => { Console.WriteLine("3. number*3 is " + n*3); });
s.Run(actionIfB: str => { Console.WriteLine("4. uppercase string is " + str.ToUpper()); });
i.Run(actionIfA: n => { Console.WriteLine("5. number*3 is " + n*3); });
Console.WriteLine("does i equals s:" + i.Equals(s));
如果你想在一個更緊迫/稍快/不太安全的方式來使用它 使標籤和值的公共(或使標籤公衆和使用get (A/B/C/D/E)OrThrow方法,如果以錯誤的方式使用,則啓用更好的異常)並使用if/else或打開它以使用AValue/BValue(/ CValue/DValue/EValue,如果您正在使用一個3/4/5元組)。請注意,這使得你不可能強迫你處理所有的狀態,並且使你更容易混淆並使用錯誤的類型。
它與「元組」或「元組」有什麼不同?示例的使用可能會澄清你的目標... –
你能更清楚一點你想達到什麼嗎?我不明白這個預期設計的原因。 – PMF
也許,詞典是你在找什麼。 –