分享
 
 
 

三值逻辑的C#实现

王朝c#·作者佚名  2006-01-09
窄屏简体版  字體: |||超大  

C#中的三值逻辑类

三值逻辑的实际应用价值并未被忽视,在绝大多数介绍关系型数据库知识的书籍中,都涉及了NULL值的讨论,也少不了三值逻辑。而MSDN中,则给出了一个用C#实现的三值逻辑结构(struct),在应用层提供了三值逻辑运算功能。相关文章转贴如下:

C# Language Specification

11.4.2 Database boolean type

The DBBool struct below implements a three-valued logical type. The possible values of this type are DBBool.True, DBBool.False, and DBBool.Null, where the Null member indicates an unknown value. Such three-valued logical types are commonly used in databases.

using System;

public struct DBBool

{

// The three possible DBBool values.

public static readonly DBBool Null = new DBBool(0);

public static readonly DBBool False = new DBBool(-1);

public static readonly DBBool True = new DBBool(1);

// Private field that stores –1, 0, 1 for False, Null, True.

sbyte value;

// Private instance constructor. The value parameter must be –1, 0, or 1.

DBBool(int value) {

this.value = (sbyte)value;

}

// Properties to examine the value of a DBBool. Return true if this

// DBBool 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 DBBool. Maps true to DBBool.True and

// false to DBBool.False.

public static implicit operator DBBool(bool x) {

return x? True: False;

}

// Explicit conversion from DBBool to bool. Throws an exception if the

// given DBBool is Null, otherwise returns true or false.

public static explicit operator bool(DBBool x) {

if (x.value == 0) throw new InvalidOperationException();

return x.value > 0;

}

// Equality operator. Returns Null if either operand is Null, otherwise

// returns True or False.

public static DBBool operator ==(DBBool x, DBBool 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 DBBool operator !=(DBBool x, DBBool 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 DBBool operator !(DBBool x) {

return new DBBool(-x.value);

}

// Logical AND operator. Returns False if either operand is False,

// otherwise Null if either operand is Null, otherwise True.

public static DBBool operator &(DBBool x, DBBool y) {

return new DBBool(x.value < y.value? x.value: y.value);

}

// Logical OR operator. Returns True if either operand is True, otherwise

// Null if either operand is Null, otherwise False.

public static DBBool operator |(DBBool x, DBBool y) {

return new DBBool(x.value > y.value? x.value: y.value);

}

// Definitely true operator. Returns true if the operand is True, false

// otherwise.

public static bool operator true(DBBool x) {

return x.value > 0;

}

// Definitely false operator. Returns true if the operand is False, false

// otherwise.

public static bool operator false(DBBool x) {

return x.value < 0;

}

public override bool Equals(object obj) {

if (!(obj is DBBool)) return false;

return value == ((DBBool)obj).value;

}

public override int GetHashCode() {

return value;

}

public override string ToString() {

if (value > 0) return "DBBool.True";

if (value < 0) return "DBBool.False";

return "DBBool.Null";

}

}

Send feedback on this topic to Microsoft

© Microsoft Corporation. All rights reserved.

从文章内容我们可以看出,它采用的是我们前面所述的第三种算法。这个示例搭建了一个不错的框架,除了与、或运算,还包括了必要的类型转换、比较以及在.net CLR中必不可少的GetHashCode和ToString方法。

当我们以初学者的心态面对这段朴实的代码时,有几个地方是值得学习的:

在结构内部,以-1、0、1来代表三种不同的逻辑状态。并通过定义False、NULL、True三个常量来代表所有可能该类型对象所有可能的值。这种数值与逻辑的对应符合人们常规的思维习惯和数学上的美感。也方便实现GetHashCode方法。

利用内部数值,简洁美观的实现了与/或/非运算。如果按照前面我们提的三种逻辑算法中的另外两种,实现起来就没有那么美观了。也许这就是很多关系型数据库选择这种算法实现的原因。美感,在数学体系中是一件很重要的事。

提供了IsTrue、IsFalse、IsNull判断功能,使用起来很方便。

三值逻辑向两值逻辑和DBNull转换时,必须显示转型(explicit),反之则只需要隐式转换(implicit)。

实现了true和false运算符。

重载了.net CLR要求的GetHashCode和ToString方法。当我们在特定的环境工作时,应该遵循该环境的要求和约定,而这是实际开发时经常被忽视的。

为了满足实际使用的需要,我对这个类进行了一些扩充。主要如下:

与DBNULL类型的互相转化(要考虑其中的类型转换异常)。

从字符串到三值逻辑的解析方法Parse(据此对ToString()方法有所改变)。

增加了新的构造函数。

增加了支持另外两种逻辑运算体系的与/或运算。

增加了向数据库逻辑字段赋值所用的转换函数ToDBBoolean。

新的代码如下:

using System;

namespace March.VBoolean

{

/// <summary>

/// 三值逻辑类(Bool with three),支持System.DBNull。

/// </summary>

public struct Boolw3

{

// The three possible Boolw3 values.

public static readonly Boolw3 Null = new Boolw3(0);

public static readonly Boolw3 False = new Boolw3(-1);

public static readonly Boolw3 True = new Boolw3(1);

// Private field that stores –1, 0, 1 for False, Null, True.

sbyte value;

// Private instance constructor. The value parameter must be –1, 0, or 1.

Boolw3(int value)

{

this.value = (sbyte)value;

}

public Boolw3(bool value)

{

this.value = value? (sbyte)1:(sbyte)-1;

}

public Boolw3(DBNull value)

{

this.value = (sbyte)0;

}

/// <summary>

/// 从数据库组件的逻辑字段值中构造实例

/// </summary>

/// <param name="?">只能为System.Boolean或DBNull类型。</param>

public Boolw3(object value)

{

if(null == value)

throw new ArgumentException("The value must in true, false or DBNull!");

if(value.GetType() == typeof(bool))

{

this.value = (bool)value?(sbyte)1:(sbyte)-1;

return;

}

if(value.GetType() == typeof(DBNull))

{

this.value = (sbyte)0;

return;

}

throw new ArgumentException("The value must in true, false or DBNull!");

}

/// <summary>

/// 从字符串解析值。

/// </summary>

/// <param name="value">可选值为可能带有限定名"Boolw3"的"True"、"False"、"Null"</param>

public static Boolw3 Parse(string value)

{

Boolw3 Re = Null;

switch(value)

{

case "Boolw3.True":

case "True" :

{

Re.value = (sbyte)1;

break;

}

case "Boolw3.False":

case "False":

{

Re.value = (sbyte)-1;

break;

}

case "Boolw3.Null":

case "Null":

{

Re.value = (sbyte)0;

break;

}

default:

throw new ArgumentException("The value must in \"Boolw3.True\", \"Boolw3.False\" ,\"Boolw3.Null\", \"True\", \"False\" or \"Null\"!");

}

return Re;

}

// 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 Boolw3(bool x)

{

return x? True: False;

}

public static implicit operator Boolw3(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(Boolw3 x)

{

if (x.value == 0) throw new InvalidOperationException();

return x.value > 0;

}

public static explicit operator DBNull(Boolw3 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 Boolw3 operator ==(Boolw3 x, Boolw3 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 Boolw3 operator !=(Boolw3 x, Boolw3 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 Boolw3 operator !(Boolw3 x)

{

return new Boolw3(-x.value);

}

// Logical AND operator. Returns False if either operand is False,

// otherwise Null if either operand is Null, otherwise True.

public static Boolw3 operator &(Boolw3 x, Boolw3 y)

{

return new Boolw3(x.value < y.value? x.value: y.value);

}

// Logical OR operator. Returns True if either operand is True, otherwise

// Null if either operand is Null, otherwise False.

public static Boolw3 operator |(Boolw3 x, Boolw3 y)

{

return new Boolw3(x.value > y.value? x.value: y.value);

}

/// <summary>

/// VerifyAnd事实上是一种以Null值为最低优先级的逻辑与操作。通常用于验证数据有效性。

/// 两个操作数中至少有一个为False时返回False,否则,至少有一个为True时为True,否

/// 则返回NULL。

/// </summary>

/// <param name="x">左操作数</param>

/// <param name="y">右操作数</param>

/// <returns>运算结果为Boolw3类型</returns>

public static Boolw3 VerifyAnd(Boolw3 x, Boolw3 y)

{

if (x.value == -1 || y.value == -1) return False;

if (x.value == 1 || y.value == 1) return True;

return Null;

}

/// <summary>

/// VerifyOr事实上是一种以Null值为最低优先级的逻辑或操作。通常用于验证数据有效性。

/// 两个操作数中至少有一个为True时返回True,否则,至少有一个为False时返回False,否

/// 则返回NULL。

/// </summary>

/// <param name="x">左操作数</param>

/// <param name="y">右操作数</param>

/// <returns>运算结果为Boolw3类型</returns>

public static Boolw3 VerifyOr(Boolw3 x, Boolw3 y)

{

if (x.value == 1 || y.value == 1) return True;

if (x.value == -1 & y.value == -1) return False;

return True;

}

/// <summary>

/// DBAnd是以Null值为最高优先值的逻辑与操作,常见于某些数据库平台。当操作数中有一个为

/// Null,返回值为Null,其它与二值逻辑相同。

/// </summary>

/// <param name="x">左操作数</param>

/// <param name="y">右操作数</param>

/// <returns>运算结果为Boolw3类型</returns>

public static Boolw3 DBAnd(Boolw3 x, Boolw3 y)

{

if (x.value == 0 || y.value ==0) return Null;

return new Boolw3(x.value < y.value ? x.value : y.value);

}

/// <summary>

/// DBOr是以Null值为最高优先值的逻辑或操作,常见于某些数据库平台。当操作数中有一个为

/// Null,返回值为Null,其它与二值逻辑相同。

/// </summary>

/// <param name="x">左操作数</param>

/// <param name="y">右操作数</param>

/// <returns>运算结果为Boolw3类型</returns>

public static Boolw3 DBOr(Boolw3 x, Boolw3 y)

{

if (x.value == 0 || y.value ==0) return Null;

return new Boolw3(x.value > y.value ? x.value : y.value);

}

// Definitely true operator. Returns true if the operand is True, false

// otherwise.

public static bool operator true(Boolw3 x)

{

return x.value > 0;

}

// Definitely false operator. Returns true if the operand is False, false

// otherwise.

public static bool operator false(Boolw3 x)

{

return x.value < 0;

}

public override bool Equals(object obj)

{

if (!(obj is Boolw3)) return false;

return value == ((Boolw3)obj).value;

}

public override int GetHashCode()

{

return value;

}

public override string ToString()

{

if (value > 0) return "Boolw3.True";

if (value < 0) return "Boolw3.False";

return "Boolw3.Null";

}

/// <summary>

/// 用于向数据库访问组件的Boolean类型(如SqlDBType.Bit)字段赋值

/// </summary>

/// <returns>返回一个object对象,其内部封装的可能为true、false或DBNull.Value</returns>

public object ToDbBoolean()

{

return (value == 0) ? (object)DBNull.Value : (object)(value>0);

}

}

}

以上代码经实际应用,可以满足需求,但是有如下地方还值得进一步改造:

应当将三种逻辑体系放在同一个类型中实现显得很不协调,影响了代码一致性和我们的常规使用习惯。应当将通用的代码统一生成为一个基类,并用抽象方法或接口的形式规定出与/或运算实现。在三个不同的子类中实现。并在子类中实现不同子类之间的显示类型转换。为了出现不必要的强耦合,可以实现子类向基类的隐式类型转换(由于OO语言的特性,这一点默认情况下就是有效的)以及基类向子类的显式类型转换(这一点可以通过在基类中定义一个虚构造函数,由子类直接继承实现)。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有