三值逻辑的C#实现

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语言的特性,这一点默认情况下就是有效的)以及基类向子类的显式类型转换(这一点可以通过在基类中定义一个虚构造函数,由子类直接继承实现)。

时间: 2024-09-19 20:33:41

三值逻辑的C#实现的相关文章

你真的会玩SQL吗?让人晕头转向的三值逻辑

你真的会玩SQL吗?系列目录 你真的会玩SQL吗?之逻辑查询处理阶段 你真的会玩SQL吗?和平大使 内连接.外连接 你真的会玩SQL吗?三范式.数据完整性 你真的会玩SQL吗?查询指定节点及其所有父节点的方法 你真的会玩SQL吗?让人晕头转向的三值逻辑 你真的会玩SQL吗?EXISTS和IN之间的区别 你真的会玩SQL吗?无处不在的子查询 你真的会玩SQL吗?Case也疯狂 你真的会玩SQL吗?表表达式,排名函数 你真的会玩SQL吗?简单的 数据修改 你真的会玩SQL吗?你所不知道的 数据聚合

掌握SQL四条最基本的数据操作语句

数据|语句 掌握sql四条最基本的数据操作语句:insert,select,update和delete. 练掌握sql是数据库用户的宝贵财富.在本文中,我们将引导你掌握四条最基本的数据操作语句-sql的核心功能-来依次介绍比较操作符.选择断言以及三值逻辑.当你完成这些学习后,显然你已经开始算是精通sql了. 在我们开始之前,先使用create table语句来创建一个表(如图1所示).ddl语句对数据库对象如表.列和视进行定义.它们并不对表中的行进行处理,这是因为ddl语句并不处理数据库中实际的

SQL Story摘录(七)————触摸NULL值

前面的文章中,我们初步见识了NULL这个不可思议的小东西.今天,我尽可能详细的介绍一下它.依照惯例,这是一次尽量浅显但并不严谨的讨论,甚至可能内容也不那么严肃.我的目的在于帮助读者更轻松地工作,并且有兴趣对数据库进一步的学习.从另一方面讲,我相信自己论点中的错误,肯定会有其他人也在犯,所以请发现不妥的朋友一定要公开指出.这样,才有助于我和我的读者朋友们进步.衷心感谢每一个提出批评和指正的朋友,特别是公开提出批评和指正的朋友们.特别感谢sunshine19,专程发来E-mail,指出了<SQL S

sql

掌握SQL四条最基本的数据操作语句:Insert,Select,Update和Delete. 练掌握SQL是数据库用户的宝贵财 富.在本文中,我们将引导你掌握四条最基本的数据操作语句-SQL的核心功能-来依次介绍比较操作符.选择断言以及三值逻辑.当你完成这些学习后,显然你已经开始算是精通SQL了. 在我们开始之前,先使用CREATE TABLE语句来创建一个表(如图1所示).DDL语句对数据库对象如表.列和视进行定义.它们并不对表中的行进行处理,这是因为DDL语句并不处理数据库中实际的数据.这些

SQL语法大全

sql语法  SQL语法大全   SQL语法大全1. ASP与Access数据库连接: <%@ language=VBscript%><%dim conn,mdbfilemdbfile=server.mappath("数据库名称.mdb")set conn=server.createobject("adodb.connection")conn.open "driver={microsoft access driver (*.mdb)};u

【原创】bool、BOOL 和 _Bool 辨析

      最近在搞跨平台编译的时候又遇到了 C99 标准支持的问题,主要体现在布尔类型问题上面.于是乎决定把这个问题彻底搞搞清楚,遂成此文.  [ bool.BOOL 和 _Bool 的区别 ]        bool 类型在 C++ 中以关键字的形式被支持,表示布尔类型,其对应变量的值只有真(true)和假(false)两种值.        BOOL 类型在头文件 <windef.h> 中定义为 typedef int BOOL:在头文件 <wtypes.h> 中定义为 ty

Logback 专题

  spring boot中使用logback时一个一个配置文件示例:简单的:logback-spring.xml <?xml version="1.0" encoding="UTF-8"?> <configuration> <include resource="org/springframework/boot/logging/logback/base.xml" /> <logger name="

[CLR via C#]19. 可空值类型

原文:[CLR via C#]19. 可空值类型 我们知道,一个值类型的变量永远不可能为null.它总是包含值类型本身.遗憾的是,这在某些情况下会成为问题.例如,设计一个数据库时,可将一个列定义成为一个32位的整数,并映射到FCL的Int32数据类型.但是,数据库中的一个列可能允许值为空:用Microsoft .NET Framework处理数据库可能变得相当困难,因为在CLR中,没有办法将一个Int32值表示为null. Microsoft ADO.NET的表适配器确实支持可空类型.但遗憾的是

最新Oracle 和 mysql 的对比参照----开发篇(转)

  Oracle mysql 对比版本 Release 10.2.0.1.0 XE  windowsXP 5.0.45-community-nt-log MySQL Community Edition (GPL) 当作计算器 SQL> select 1+1 from dual; mysql> select 1+1; mysql> select 1+1 from dual; 显示表结构 SQL> desc 表名 mysql> desc 表名; SQL> describe