Для чего нужен фальшивый оператор в С#?
В С# есть два странных оператора:
Если я понимаю это право, эти операторы могут использоваться в типах, которые я хочу использовать вместо булевского выражения, и где я не хочу предоставлять неявное преобразование в bool.
Скажем, у меня есть следующий класс:
public class MyType
{
public readonly int Value;
public MyType(int value)
{
Value = value;
}
public static bool operator true (MyType mt)
{
return mt.Value > 0;
}
public static bool operator false (MyType mt)
{
return mt.Value < 0;
}
}
Поэтому я могу написать следующий код:
MyType mTrue = new MyType(100);
MyType mFalse = new MyType(-100);
MyType mDontKnow = new MyType(0);
if (mTrue)
{
// Do something.
}
while (mFalse)
{
// Do something else.
}
do
{
// Another code comes here.
} while (mDontKnow)
Однако для всех приведенных выше примеров выполняется только истинный оператор. Итак, для чего нужен фальшивый оператор в С#?
Примечание. Дополнительные примеры можно найти здесь, здесь и здесь.
Ответы
Ответ 1
Вы можете использовать его для переопределения операторов &&
и ||
.
Операторы &&
и ||
не могут быть переопределены, но если вы переопределите |
, &
, true
и false
точно так, как компилятор вызовет |
и &
, когда вы пишете ||
и &&
.
Например, посмотрите на этот код (из http://ayende.com/blog/1574/nhibernate-criteria-api-operator-overloading - где я узнал об этом трюке; архивная версия от @BiggsTRC):
public static AbstractCriterion operator &(AbstractCriterion lhs, AbstractCriterion rhs)
{
return new AndExpression(lhs, rhs);
}
public static AbstractCriterion operator |(AbstractCriterion lhs, AbstractCriterion rhs)
{
return new OrExpression(lhs, rhs);
}
public static bool operator false(AbstractCriterion criteria)
{
return false;
}
public static bool operator true(AbstractCriterion criteria)
{
return false;
}
Это, очевидно, побочный эффект, а не способ его использования, но он полезен.
Ответ 2
Shog9 и Nir:
спасибо за ваши ответы. Эти ответы указали мне на , и он указал мне на msdn:
Операция x && y оценивается как T.false(x)? x: T. & (x, y), где T.false(x) является вызовом оператора false, объявленного в T, и T. & (x, y) является вызовом выбранного оператора &. Другими словами, сначала оценивается x, а на результат вызывается оператор false, чтобы определить, является ли x определенно ложным. Тогда, если x определенно ложно, результатом операции является значение, ранее вычисленное для x. В противном случае y вычисляется, а выбранный оператор и вызывается на значение, ранее вычисленное для x, и значение, вычисленное для y, для получения результата операции.
Ответ 3
Страница, на которую вы ссылаетесь на http://msdn.microsoft.com/en-us/library/6x6y6z4d.aspx, говорит о том, для чего они предназначены, что было способом обработки обнуляемых переменных bools до того, как были введены типы значений NULL.
Я бы предположил, что в настоящее время они хороши для того же типа вещей, что и ArrayList, т.е. абсолютно ничего.
Ответ 4
AFAIK, он будет использоваться в тесте для false, например, когда оператор &&
вступает в игру. Помните, && коротких замыканий, поэтому в выражении
if ( mFalse && mTrue)
{
// ... something
}
mFalse.false()
вызывается, а при возврате true
выражение сводится к вызову 'mFalse.true()' (который затем должен возвращать false
, или вещи будут странными).
Обратите внимание, что вы должны реализовать оператор &
для компиляции этого выражения, поскольку он использовался, если mFalse.false()
возвращает false
.
Ответ 5
Из статьи MSDN, с которой вы связались, была предоставлена возможность допускать пустые типы с буфером до того, как тип Nullable (т.е. int?, bool? и т.д.) будет введен в язык С# 2. Таким образом, вы сохранили бы внутреннее значение, указывающее, является ли значение истинным или ложным или нулевым, т.е. В вашем примере > 0 для true, < 0 для false и == 0 для значения null, а затем вы получите нулевую семантику в стиле SQL, Вы также должны были бы реализовать метод или свойство .IsNull, чтобы явное недействительность nullity.
Сравнивая с SQL, представьте таблицу Table с тремя строками со значением Foo, установленным в true, 3 строки со значением Foo, установленным в false, и 3 строки со значением Foo, установленным в null.
SELECT COUNT(*) FROM Table WHERE Foo = TRUE OR Foo = FALSE
6
Чтобы подсчитать все строки, вам нужно будет сделать следующее: -
SELECT COUNT(*) FROM Table WHERE Foo = TRUE OR Foo = FALSE OR Foo IS NULL
9
Синтаксис "IS NULL" имеет эквивалентный код в вашем классе как .IsNull().
LINQ делает сравнение с С# еще более ясным: -
int totalCount = (from s in MyTypeEnumerable
where s || !s
select s).Count();
Представьте, что MyTypeEnumberable имеет точно такое же содержимое базы данных, т.е. 3 значения, равные true, 3 значения равны false и 3 значения равны нулю. В этом случае totalCount будет оценивать до 6 в этом случае. Однако, если мы повторно написали код как: -
int totalCount = (from s in MyTypeEnumerable
where s || !s || s.IsNull()
select s).Count();
Тогда totalCount будет оценивать до 9.
Пример DBNull, приведенный в статье связанного MSDN с ложным оператором, демонстрирует класс в BCL, который имеет это точное поведение.
Фактически вывод заключается в том, что вы не должны использовать это, если не уверены, что хотите этого типа поведения, лучше просто использовать гораздо более простой синтаксис с нулевым значением!
Обновление: Я просто заметил, что вам нужно вручную переопределить логические операторы!, || и && чтобы эта работа работала должным образом. Я считаю, что ложный оператор подает эти логические операторы, т.е. Указывает правду, ложность или "в противном случае". Как отмечено в другом комментарии! X не будет работать с места в карьер; вам нужно перегружать! Weirdness!