Pregunta

Hay dos operadores extraños en C#:

Si entiendo bien, estos operadores se pueden usar en tipos que quiero usar en lugar de una expresión booleana y donde no quiero proporcionar una conversión implícita a bool.

Digamos que tengo la siguiente clase:

    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 operador falso en C#?

Nota:Se pueden encontrar más ejemplos. aquí, aquí y aquí.

¿Fue útil?

Solución

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

El && y || Los operadores no se pueden anular, pero si anulas |, &, true y false exactamente de la manera correcta que el compilador llamará | y & cuando escribes || 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;
}

Obviamente, esto es un efecto secundario y no la forma en que debe usarse, pero es útil.

Otros consejos

Shog9 y Nir:Gracias por tus respuestas.Esas respuestas me indicaron Artículo de Steve Eichert y me señaló 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 falso declarado en T, y T.&(x, y) es una invocación del operador seleccionado &.En otras palabras, primero se evalúa x y se invoca el operador falso 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, se evalúa y y se invoca el operador seleccionado & en el valor calculado previamente para x y el valor calculado para y para producir el resultado de la operación.

La página a la que enlazas http://msdn.microsoft.com/en-us/library/6x6y6z4d.aspx dice para qué servían, que era una forma de manejar bools que aceptan valores NULL antes de que se introdujeran los tipos de valores que aceptan valores NULL.

Supongo 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 de falso, como cuando el && El operador entra en juego.Recuerde, && cortocircuitos, por lo que en la expresión

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

mFalse.false() es llamado, y al regresar 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() devoluciones false.

Según el artículo de MSDN al que vinculó, se proporcionó para permitir tipos booleanos anulables antes de Nullable (es decir,int?, bool?, etc.) que se introduce en el lenguaje en C#2.Por lo tanto, almacenaría un valor interno que indica si el valor es verdadero, falso o nulo, es decir.en su ejemplo >0 para verdadero, <0 para falso y ==0 para nulo, y luego obtendría una semántica nula de estilo SQL.También tendría que implementar un método o propiedad .IsNull para que la nulidad pueda verificarse explícitamente.

En comparación con SQL, imagine una tabla con 3 filas con el valor Foo establecido en verdadero, 3 filas con el valor Foo establecido en falso y 3 filas con el valor Foo establecido en nulo.

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

Para contar todas las filas, tendrías que hacer lo siguiente:-

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

Esta sintaxis 'IS NULL' tendría un 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 el mismo contenido de la base de datos, es decir3 valores iguales a verdadero, 3 valores iguales a falso y 3 valores iguales a nulo.En este caso, totalCount se evaluaría como 6.Sin embargo, si reescribimos el código como: -

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

Entonces totalCount se evaluaría como 9.

El ejemplo de DBNull que se proporciona en el artículo de MSDN vinculado sobre el operador falso demuestra una clase en BCL que tiene exactamente este comportamiento.

En efecto, la conclusión es que no deberías usar esto a menos que estés completamente seguro de que quieres este tipo de comportamiento, ¡es mejor usar la sintaxis anulable mucho más simple!

Actualizar: ¡Acabo de notar que necesita anular manualmente los operadores lógicos!, || y && para que esto funcione correctamente.Creo que el operador falso alimenta estos operadores lógicos, es decirindicando verdad, falsedad o "lo contrario".Como se señaló en otro comentario, !x no funcionará desde el principio;¡hay que sobrecargar!.¡Rareza!

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top