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