tags:

views:

156

answers:

2

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) { ... }
+2  A: 

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.

Marc Gravell
Thanks! Although, could you explain why I might want to make this an immutable struct?
David Brown
I'll edit to illustrate (it is too long for a comment).
Marc Gravell
+1  A: 

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

}
driis