Обработка сравнений с пользовательским логическим типом? - PullRequest
3 голосов
/ 25 февраля 2009

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

3 голосов
/ 25 февраля 2009

Есть две вещи, на которые стоит посмотреть; оператор неявного преобразования (в 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. Если это было намерение, тогда хорошо. Но если бы это был я, я бы сделал его неизменным (класс или структура). Но так как у него нет состояния, отличного от bool, я бы сказал, что это хорошо подходит как структура.

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

1 голос
/ 25 февраля 2009

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

}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...