以前的文章中,我们讨论了三值逻辑可能的运算体系和可能的代码实现。这里,我们给出一种完全的实现方式。以下代码利用枚举,在每一个三值逻辑对象中标识出其认可的算法,如果两个对象认可的与/或算法不一致,则抛出异常。出于程序结构上的完整性限制,逻辑对象具有默认算法——Arithmetics.Mathemetic。但是,我们可以在运行期修改它这个标识,也可以通过工厂方法方便的得到指定算法的对象。
以下为算法标识枚举Arithmetics的定义:
public enum Arithmetics {Mathematic, Database, Verify};
以下为三值逻辑结构的代码,从不同的与/或运算静态方法的名字上,我们可以看出它们支持的算法。当然,如您所见,这种设计结构是封闭的,我们不能为它添加新的算法——从实用角度上看,这三种算法已经可以应付几乎所有场合了。
public struct VarBool
{
// The three possible Boolw3 values.
public static readonly VarBool Null = new VarBool(0);
public static readonly VarBool False = new VarBool(-1);
public static readonly VarBool True = new VarBool(1);
// private field that stores –1, 0, 1 for False, Null, True.
private sbyte value;
private Arithmetics _Arithmetic;
public Arithmetics Arithmetic
{
get
{
return _Arithmetic;
}
set
{
_Arithmetic = value;
}
}
// private instance constructor. The value parameter must be –1, 0, or 1.
private VarBool(int value)
{
this.value = (sbyte)value;
this._Arithmetic = Arithmetics.Mathematic;
}
/// <summary>
/// 从数据库组件的逻辑字段值中构造实例
/// </summary>
/// <param name="value">只能为System.Boolean或DBNull类型。</param>
public static VarBool Read(object value)
{
if(null == value)
throw new ArgumentException("The value is null!");
if(value is bool || value is DBNull)
return (VarBool)value;
else
throw new ArgumentException("The value must in true, false or DBNull!");
}
/// <summary>
/// 从字符串解析值。
/// </summary>
/// <param name="value">可选值为"True"、"False"、"Null"</param>
public static VarBool Parse(string value)
{
switch(value)
{
case "True" :
{
return True;
}
case "False":
{
return False;
}
case "Null":
{
return Null;
}
default:
throw new ArgumentException("The value must in \"True\", \"False\" or \"Null\"!");
}
}
// Properties to examine the value of a Boolw3. Return true if this
// Boolw3 has the given value, false otherwise.
public bool IsNull { get { return value == 0; } }
public bool IsFalse { get { return value < 0; } }
public bool IsTrue { get { return value > 0; } }
// Implicit conversion from bool to Boolw3. Maps true to Boolw3.True and
// false to Boolw3.False.
public static implicit operator VarBool(bool x)
{
return x? True: False;
}
public static implicit operator VarBool(DBNull x)
{
return Null;
}
// Explicit conversion from Boolw3 to bool.Throws an exception if the
// given Boolw3 is Null, otherwise returns true or false.
public static explicit operator bool(VarBool x)
{
if (x.value == 0) throw new InvalidOperationException();
return x.value > 0;
}
public static explicit operator DBNull(VarBool x)
{
if (x.value != 0) throw new InvalidOperationException();
return DBNull.Value;
}
// Equality operator. Returns Null if either operand is Null, otherwise
// returns True or False.
public static VarBool operator ==(VarBool x, VarBool y)
{
if (x.value == 0 || y.value == 0) return Null;
return x.value == y.value? True: False;
}
// Inequality operator. Returns Null if either operand is Null, otherwise
// returns True or False.
public static VarBool operator !=(VarBool x, VarBool y)
{
if (x.value == 0 || y.value == 0) return Null;
return x.value != y.value? True: False;
}
// Logical negation operator. Returns True if the operand is False, Null
// if the operand is Null, or False if the operand is True.
public static VarBool operator !(VarBool x)
{
return new VarBool(-x.value);
}
public override bool Equals(object obj)
{
return base.Equals (obj);
}
public override int GetHashCode()
{
return this.value;
}
public override string ToString()
{
if (value > 0) return "True";
if (value < 0) return "False";
return "Null";
}
public static VarBool MathAnd(VarBool x, VarBool y)
{
return new VarBool(x.value < y.value? x.value: y.value);
}
public static VarBool MathOr(VarBool x, VarBool y)
{
return new VarBool(x.value > y.value? x.value: y.value);
}
public static VarBool DBAnd(VarBool x, VarBool y)
{
if (x.value == 0 || y.value ==0) return Null;
return new VarBool(x.value < y.value ? x.value : y.value);
}
public static VarBool DBOr(VarBool x, VarBool y)
{
if (x.value == 0 || y.value ==0) return Null;
return new VarBool(x.value > y.value ? x.value : y.value);
}
public static VarBool VerifyAnd(VarBool x, VarBool y)
{
if (x.value == -1 || y.value == -1) return False;
if (x.value == 1 || y.value == 1) return True;
return Null;
}
public static VarBool VerifyOr(VarBool x, VarBool y)
{
if (x.value == 1 || y.value == 1) return True;
if (x.value == -1 & y.value == -1) return False;
return True;
}
public static VarBool operator &(VarBool x, VarBool y)
{
if(x.Arithmetic != y.Arithmetic)
throw new ArgumentException(string.Format("左参数选择了{0}算法,而右参数选择了{1}算法。", x.Arithmetic, y.Arithmetic));
switch(x.Arithmetic)
{
case Arithmetics.Database:
return DBAnd(x, y);
case Arithmetics.Mathematic:
return MathAnd(x, y);
case Arithmetics.Verify:
return VerifyAnd(x, y);
default:
return Null;
}
}
public static VarBool operator |(VarBool x, VarBool y)
{
if(x.Arithmetic != y.Arithmetic)
throw new ArgumentException(string.Format("左参数选择了{0:D}算法,而右参数选择了{1:D}算法。", x.Arithmetic, y.Arithmetic));
switch(x.Arithmetic)
{
case Arithmetics.Database:
return DBOr(x, y);
case Arithmetics.Mathematic:
return MathOr(x, y);
case Arithmetics.Verify:
return VerifyOr(x, y);
default:
return Null;
}
}
}
以下为三值逻辑类的工厂方法类。通过工厂类的构造函数参数,我们可以指定即将生成的三值逻辑对象支持何种算法,这使得我们可以通过更简单和直观的方式生成对象。
/// <summary>
/// VarBool 的工厂方法集合,封装算法选择。
/// 如果不通过该工厂生成VarBool,其默认算
/// 法为Mathematic,也可以在运行期修改
/// Arithmetic属性来指定算法。
/// </summary>
public class VarBoolBuilder
{
private Arithmetics _Arithmetic;
public VarBoolBuilder(Arithmetics Arithmetic)
{
_Arithmetic = Arithmetic;
}
public VarBool Null
{
get
{
VarBool re = VarBool.Null;
re.Arithmetic = _Arithmetic;
return re;
}
}
public VarBool True
{
get
{
VarBool re = VarBool.True;
re.Arithmetic = _Arithmetic;
return re;
}
}
public VarBool False
{
get
{
VarBool re = VarBool.False;
re.Arithmetic = _Arithmetic;
return re;
}
}
public VarBool Read(object value)
{
VarBool re = VarBool.Read(value);
re.Arithmetic = _Arithmetic;
return re;
}
public VarBool Parse(string value)
{
VarBool re = VarBool.Parse(value);
re.Arithmetic = _Arithmetic;
return re;
}
}