Обработка сравнений с пользовательским логическим типом?

У меня есть пользовательский объект, который отображает логическое значение из устаревшей базы данных в 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 ответа

Решение

Есть две вещи, на которые стоит посмотреть; оператор неявного преобразования (в 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?

Это печатает ложь, потому что оба IsActive поля указывают на один и тот же экземпляр S2kBool, Если это было намерение, тогда хорошо. Но если бы это был я, я бы сделал его неизменным (класс или структура). Но так как у него нет другого состояния, кроме bool, я бы сказал, что это хорошо вписывается в структуру.

Если честно, я не совсем уверен, зачем это вообще нужно, когда вся функциональность может быть реализована статическими методами / и т. Д.

Да, вы можете сделать это. Вам нужно будет определить операторы равенства и переопределить метод 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);
    }

}
Другие вопросы по тегам