处理与自定义布尔类型的比较?

时间:2009-02-24 21:28:12

标签: c# comparison

我有一个自定义对象,它将来自旧数据库的布尔值映射到C#bool(并再次返回)。

我的自定义bool对象如下所示:

public class S2kBool : IUserDefinedType {
    public bool Value { get; set; }

    public Type SupportedType { get { return typeof(string); } }

    // These are the values used to represent booleans in the database
    public const string TrueValue = "Y";
    public const string FalseValue = "N";

    public static S2kBool True {
        get { return new S2kBool(true); }
    }

    public static S2kBool False {
        get { return new S2kBool(false); }
    }

    public S2kBool() : this(false) { }

    public S2kBool(bool value) {
        this.Value = value;
    }

    // Called when a property of this type is populated from the database
    public void FromSimpleDataType(object value) {
        this.Value = value.ToString() == TrueValue;
    }

    // Called when a property of this type is inserted into the database
    public object ToSimpleDataType() {
        return this.Value ? TrueValue : FalseValue;
    }
}

我希望能够做到这样的事情:

public class TestObject {
    public S2kBool IsActive = S2kBool.True;
}

TestObject tObj = new TestObject();
if (tObj.IsActive == S2kBool.True) {
    // the above would evaluate to true
}

我已经看到了几种不同的对象之间进行比较的方法,但我不确定要使用哪种方法。

编辑:更好的是,是否可以执行以下操作并让C#在比较期间将S2kBool对象视为实际的布尔值?它还应该允许与其他S2kBool对象进行比较。

if (tObj.IsActive == true) { ... }

2 个答案:

答案 0 :(得分:3)

有两件事需要注意;隐式转换运算符(在S2kBool中)到bool,或true / false运算符本身......


true / false操作符(注意我更喜欢自己的隐式bool转换):

public static bool operator true(S2kBool x) {
    return x.Value;
}
public static bool operator false(S2kBool x) {
    return !x.Value;
}

然后您可以使用if(tObj.IsActive)


转换运算符:

public static implicit operator bool(S2kBool x) {
    return x.Value;
}

同样适用


您也可以在另一个方向添加转化:

public static implicit operator S2kBool(bool x)
{
    return new S2kBool(x);
}

然后您可以指定IsActive = false;


最后,我想知道这应该是一个不可变的结构吗?如果您希望它的行为类似于值,则可能会令人困惑。例如,请查看最后一行:

TestObject obj1 = new TestObject(),
           obj2 = new TestObject();
obj1.IsActive = obj2.IsActive = S2kBool.True;

Console.WriteLine(obj1.IsActive);
Console.WriteLine(obj2.IsActive);

obj1.IsActive.Value = false;

Console.WriteLine(obj1.IsActive);
Console.WriteLine(obj2.IsActive); // what does this print?

这打印为false,因为两个IsActive字段都指向S2kBool的相同实例。如果这是意图,那很好。但如果是我,我会让它变成不可变的(无论是类还是结构)。但是因为除了布尔之外它没有任何其他状态,我认为这非常适合作为结构。

说实话,我不是完全确定为什么它需要在所有,当所有功能都可以通过静态方法/等完成时。

答案 1 :(得分:1)

是的,你可以这样做。您需要定义相等运算符并覆盖Equals方法。

这是一篇关于运算符重载的文章: http://www.csharphelp.com/archives/archive135.html

以下是具有重写的相等运算符的类型的示例。您可以对赋值和转换运算符执行相同的操作,使您的类型与内置bool类型无缝协作。 (我举了你的例子,缩短了一点以保持示例简短,并添加了相等的运算符)。

public struct S2kBool : IEquatable<bool>
{
    public bool Value { get; set; }


    public bool Equals(bool other)
    {
        return Value == other;
    }

    public override int GetHashCode()
    {
        return Value.GetHashCode();
    }

    public static bool operator ==(bool left, S2kBool right)
    {
        return right.Equals(left);
    }

    public static bool operator !=(bool left, S2kBool right)
    {
        return !(left == right);
    }

    public static bool operator ==(S2kBool left, bool right)
    {
        return left.Equals(right);
    }

    public static bool operator !=(S2kBool left, bool right)
    {
        return !(left == right);
    }

}