¿Para qué sirve el falso operador en C #?

Hay dos operadores raros en C #:

  • el verdadero operador
  • el falso operador

Si entiendo este derecho, estos operadores pueden usarse en tipos que deseo usar en lugar de una expresión booleana y en los que no deseo proporcionar una conversión implícita a bool.

Digamos que tengo una clase siguiente:

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

Entonces puedo escribir el siguiente código:

  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) 

Sin embargo, para todos los ejemplos anteriores solo se ejecuta el operador verdadero. Entonces, ¿para qué sirve el falso operador en C #?

Nota: Más ejemplos se pueden encontrar aquí , aquí y aquí .

Puedes usarlo para anular el && y || operadores.

El && y || los operadores no pueden ser anulados, pero si anula | , & , true y false exactamente de la manera correcta en que el comstackdor llamará | y & cuando escribas || y && .

Por ejemplo, mire este código (de http://ayende.com/blog/1574/nhibernate-criteria-api-operator-overloading – donde descubrí este truco, versión archivada por @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; } 

Esto es obviamente un efecto secundario y no de la manera en que está destinado a ser utilizado, pero es útil.

Shog9 y Nir: gracias por tus respuestas. Esas respuestas me señalaron el artículo de Steve Eichert y me señaló a msdn :

La operación x && y se evalúa como T.false (x)? x: T. & (x, y), donde T.false (x) es una invocación del operador false declarada en T, y T. & (x, y) es una invocación del operador seleccionado &. En otras palabras, x se evalúa primero y el operador falso se invoca en el resultado para determinar si x es definitivamente falso. Entonces, si x es definitivamente falso, el resultado de la operación es el valor previamente calculado para x. De lo contrario, y se evalúa, y el operador seleccionado & se invoca en el valor calculado previamente para xy el valor calculado para y para producir el resultado de la operación.

La página que enlaza a http://msdn.microsoft.com/en-us/library/6x6y6z4d.aspx dice para qué eran, que era una forma de manejar bools anulables antes de que se introdujeran los tipos de valor anulables.

Creo que hoy en día son buenos para el mismo tipo de cosas que ArrayList, es decir, absolutamente nada.

AFAIK, se usaría en una prueba para falsa, como cuando el operador && entra en juego. Recuerde, && cortocircuitos, entonces en la expresión

 if ( mFalse && mTrue) { // ... something } 

mFalse.false() , y al volverse true la expresión se reduce a una llamada a ‘mFalse.true ()’ (que luego debería devolver false , o las cosas se pondrán raras).

Tenga en cuenta que debe implementar el operador & para que esa expresión se compile, ya que se usa si mFalse.false() devuelve false .

Parece que desde el artículo de MSDN al que se vinculó se proporcionó para permitir los tipos booleanos que aceptan nulos antes de introducir el tipo Nullable (es decir, int ?, bool ?, etc.) en el lenguaje en C # 2. De este modo, almacenaría un valor interno que indica si el valor es verdadero o falso o nulo, es decir, en su ejemplo> 0 para verdadero, <0 para falso y == 0 para nulo, y luego obtendría semántica nula de estilo SQL. También debería implementar un método o propiedad .IsNull para que la nulidad se pueda verificar explícitamente.

Comparando con SQL, imagine una tabla Tabla con 3 filas con el valor Foo establecido en verdadero, 3 filas con valor Foo establecido en falso y 3 filas con valor Foo establecido en nulo.

 SELECT COUNT(*) FROM Table WHERE Foo = TRUE OR Foo = FALSE 6 

Para contar todas las filas, debe hacer lo siguiente:

 SELECT COUNT(*) FROM Table WHERE Foo = TRUE OR Foo = FALSE OR Foo IS NULL 9 

Esta syntax ‘IS NULL’ tendría código equivalente en su clase como .IsNull ().

LINQ hace que la comparación con C # sea aún más clara: –

 int totalCount = (from s in MyTypeEnumerable where s || !s select s).Count(); 

Imaginando que MyTypeEnumberable tiene exactamente los mismos contenidos de la base de datos, es decir, 3 valores iguales a verdadero, 3 valores igual a falso y 3 valores igual a nulo. En este caso, totalCount evaluaría a 6 en este caso. Sin embargo, si volvemos a escribir el código como:

 int totalCount = (from s in MyTypeEnumerable where s || !s || s.IsNull() select s).Count(); 

Entonces totalCount evaluaría a 9.

El ejemplo DBNull dado en el artículo enlazado de MSDN en el operador falso demuestra una clase en el BCL que tiene este comportamiento exacto.

En efecto, la conclusión es que no debes usar esto a menos que estés completamente seguro de que quieres este tipo de comportamiento, ¡es mejor usar la syntax nullable mucho más simple!

Actualización: ¡Acabo de notar que necesitas anular manualmente los operadores lógicos!, || y && para hacer que esto funcione correctamente. Creo que el operador falso alimenta estos operadores lógicos, es decir, indica la verdad, la falsedad o “de lo contrario”. Como se señaló en otro comentario! X no funcionará fuera del bate; tienes que sobrecargar! ¡Rareza!