Pergunta

Existem dois operadores estranhos em C#:

Se bem entendi, esses operadores podem ser usados ​​em tipos que desejo usar em vez de uma expressão booleana e onde não quero fornecer uma conversão implícita para bool.

Digamos que eu tenha a seguinte classe:

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

    }

Então posso escrever o seguinte 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)

No entanto, para todos os exemplos acima, apenas o operador verdadeiro é executado.Então, para que serve o operador falso em C#?

Observação:Mais exemplos podem ser encontrados aqui, aqui e aqui.

Foi útil?

Solução

Você pode usá-lo para substituir o && e || operadores.

O && e || operadores não podem ser substituídos, mas se você substituir |, &, true e false exatamente da maneira certa que o compilador chamará | e & quando você escreve || e &&.

Por exemplo, veja este código (de http://ayende.com/blog/1574/nhibernate-criteria-api-operator-overloading - onde descobri esse truque; versão arquivada 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, este é um efeito colateral e não a forma como deve ser usado, mas é útil.

Outras dicas

Shog9 e Nir:obrigado por suas respostas.Essas respostas me apontaram para Artigo de Steve Eichert e isso me indicou msdn:

A operação x && y é avaliada como T.false(x) ?x:T.&(x, y), onde T.false(x) é uma invocação do operador false declarado em T, e T.&(x, y) é uma invocação do operador & selecionado.Em outras palavras, x é primeiro avaliado e o operador false é invocado no resultado para determinar se x é definitivamente falso.Então, se x for definitivamente falso, o resultado da operação será o valor previamente calculado para x.Caso contrário, y é avaliado e o operador & selecionado é invocado no valor calculado anteriormente para x e no valor calculado para y para produzir o resultado da operação.

A página para a qual você vincula http://msdn.microsoft.com/en-us/library/6x6y6z4d.aspx diz para que serviam, que era uma maneira de lidar com bools anuláveis ​​antes da introdução dos tipos de valor anuláveis.

Eu acho que hoje em dia eles são bons para o mesmo tipo de coisa que ArrayList - ou seja,absolutamente nada.

AFAIK, seria usado em um teste para falso, como quando o && operador entra em jogo.Lembre-se, && curto-circuito, então na expressão

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

mFalse.false() é chamado, e ao retornar true a expressão é reduzida a uma chamada para 'mFalse.true()' (que deve então retornar false, ou as coisas ficarão estranhas).

Observe que você deve implementar o & operador para que essa expressão seja compilada, já que é usado se mFalse.false() retorna false.

Parece que o artigo do MSDN ao qual você vinculou foi fornecido para permitir tipos booleanos anuláveis ​​antes do Anulável (ou seja,int?, bool?, etc.) sendo introduzido na linguagem em C#2.Assim, você armazenaria um valor interno indicando se o valor é verdadeiro, falso ou nulo, ou seja,no seu exemplo >0 para verdadeiro, <0 para falso e ==0 para nulo, e então você obteria semântica nula no estilo SQL.Você também teria que implementar um método ou propriedade .IsNull para que a nulidade pudesse ser verificada explicitamente.

Comparando com SQL, imagine uma tabela Table com 3 linhas com valor Foo definido como verdadeiro, 3 linhas com valor Foo definido como falso e 3 linhas com valor Foo definido como nulo.

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

Para contar todas as linhas, você teria que fazer o seguinte: -

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

Esta sintaxe 'IS NULL' teria código equivalente em sua classe como .IsNull().

LINQ torna a comparação com C# ainda mais clara: –

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

Imaginando que MyTypeEnumberable tenha exatamente o mesmo conteúdo do banco de dados, ou seja,3 valores iguais a verdadeiro, 3 valores iguais a falso e 3 valores iguais a nulo.Neste caso, totalCount seria avaliado como 6.No entanto, se reescrevermos o código como: –

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

Então totalCount seria avaliado como 9.

O exemplo DBNull dado no artigo vinculado do MSDN sobre o operador false demonstra uma classe na BCL que tem esse comportamento exato.

Na verdade, a conclusão é que você não deve usar isso a menos que tenha certeza absoluta de que deseja esse tipo de comportamento; é melhor usar apenas a sintaxe anulável, muito mais simples!!

Atualizar: Acabei de notar que você precisa substituir manualmente os operadores lógicos!, || e && para fazer isso funcionar corretamente.Acredito que o operador falso alimenta esses operadores lógicos, ou seja,indicando verdade, falsidade ou 'não'.Conforme observado em outro comentário, !x não funcionará imediatamente;você tem que sobrecarregar!Estranheza!

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top