简体   繁体   中英

Handling comparisons with a custom boolean type?

I have a custom object that maps a boolean value from a legacy database to a C# bool (and back again).

My custom bool object looks like this:

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;
    }
}

I would like to be able to do something like this:

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

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

I've seen a few different methods for doing comparisons between objects, but I'm not sure of which one to use.

EDIT: Better yet, would it be possible to do something like the following and have C# treat the S2kBool object as an actual Boolean during comparison? It should also allow comparisons with other S2kBool objects, as well.

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

There are 2 things to look at; an implicit conversion operator (in S2kBool ) to bool , or the true / false operators themselves...


true/false operators (note I prefer the implicit bool conversion myself):

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

then you can use if(tObj.IsActive)


conversion operator:

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

works likewise


You might also add a conversion in the other direction:

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

Then you can assign IsActive = false; etc


Finally, I wonder if this should be an immutable struct? It might be confusing if you expect this to behave like a value. For example, look at the last line here:

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?

This prints false, because both IsActive fields point to the same instance of S2kBool . If that was the intent, then fine. But if it was me, I'd make it immutable (whether class or struct). But since it doesn't really have any state other than a bool, I'd argue that this fits well as a struct.

To be honest, I'm not entirely sure why it is needed at all , when all the functionality could be done via static methods / etc.

Yes, you can do that. You would need to define equality operators and override the Equals method.

Here is an article about operator overloading: http://www.csharphelp.com/archives/archive135.html

Here is an example of a type with overridden equality operators. You can do the same with assignment and conversion operators, making your type work seamlessly with the built-in bool type. (I took your example, shortened it a bit to keep the example short, and added the equality operators).

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);
    }

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM