?: ?? Operadores em vez de IF | ELSE

85
public string Source
{
    get
    {
        /*
        if ( Source == null ){
            return string . Empty;
        } else {
            return Source;
        }
        */
        return Source ?? string.Empty;
    }
    set
    {
        /*
        if ( Source == null ) {
            Source = string . Empty;
        } else {
            if ( Source == value ) {
                Source = Source;
            } else {
                Source = value;
            }
        }
        */
        Source == value ? Source : value ?? string.Empty;
        RaisePropertyChanged ( "Source" );
    }
}

Posso usar ?: ??operadores EXATAMENTE como If / Else?


Minha pergunta:
Como escrever o seguinte com?: ?? operadores

[1]

if ( Source == null ){
    // Return Nothing
} else {
    return Source;
}

[2]

if ( Source == value ){
    // Do Nothing
} else {
    Source = value;
    RaisePropertyChanged ( "Source" );
} 

Resumidamente : Como não fazer nada, não retornar nada e fazer várias instruções com o ?: ??operador?

Ahmed Ghoneim
fonte
1
Ele não se comportará da mesma maneira. Ao não usar a ramificação if / else condicional, você está reatribuindo incondicionalmente (e desnecessariamente) a variável toda vez que a acessa. Isso pode dar errado muito rapidamente, especialmente se você tiver um código multithread. Só não faça isso.
Jeff Mercado
1
Você terá uma chamada interminável / recursiva se o acessor get da propriedade Source estiver retornando a propriedade Source (seu acessador get).
John K
1
Seu primeiro snippet de código tem um getter de propriedade que chama seu próprio setter , que por sua vez chama recursivamente seu próprio getter . Você me perdeu lá, já que não há nenhuma maneira de algo assim funcionar no campo. Refine sua pergunta e explique exatamente o que você deseja alcançar.
Frédéric Hamidi
Não devolver nada? Isso é VB. Você está escrevendo c # aqui.
Tarefa
@Task Quero dizer como fazer isso, esta linha é um comentário para a pergunta
Ahmed Ghoneim

Respostas:

199

Para [1], você não pode: esses operadores são feitos para retornar um valor, não para realizar operações.

A expressão

a ? b : c

avalia se bse aé verdadeiro e se avalia cse aé falso.

A expressão

b ?? c

avalia bse bse não é nulo e se avalia cse bé nulo.

Se você escrever

return a ? b : c;

ou

return b ?? c;

eles sempre retornarão algo.

Para [2], você pode escrever uma função que retorna o valor correto que executa suas "operações múltiplas", mas isso provavelmente é pior do que apenas usar if/else.

veracidade
fonte
41

O operador ternário ( ?:) não foi projetado para controlar o fluxo , mas apenas para atribuição condicional . Se você precisa controlar o fluxo de seu programa, use uma estrutura de controle, como if/ else.

Oliver Charlesworth
fonte
5
Acrescentarei que já vi pessoas usarem expressões ternárias aninhadas no lugar de if / else e isso produz código difícil de ler e depurar. Mojo ruim ao redor.
ckramer
4
Às vezes, os operadores ternários aninhados produzem um código mais legível, se o espaço em branco for usado corretamente.
verdade
2
@truth: Sim, não tenho nada contra aninhados ?:per se. Mas eu tenho um grande problema com eles sendo usados ​​para fluxo de controle, e especialmente fluxo de controle aninhado !
Oliver Charlesworth
11

Referindo-se a ?: Operador (referência C #)

O operador condicional (? :) retorna um de dois valores, dependendo do valor de uma expressão booleana. A seguir está a sintaxe do operador condicional.

Referindo-se a ?? Operador (referência C #)

O ?? operador é chamado de operador de coalescência nula e é usado para definir um valor padrão para tipos de valor anuláveis, bem como tipos de referência. Retorna o operando esquerdo se não for nulo; caso contrário, retorna o operando correto.

Que significa:

[Parte 1]

return source ?? String.Empty;

[Parte 2] não é aplicável ...

Akram Shahda
fonte
3
Isso é diferente de não fazer nada. Ele retorna uma string vazia.
verdade
1
Claro, mas não foi isso que o OP pediu. Não é minha culpa que o OP pediu para "retornar nada" - seja lá o que isso possa significar.
verdade
1
@trutheality: Nenhum órgão disse que é sua culpa .. Porém, o OP não quis devolver nada e foi isso que eu forneci.
Akram Shahda 01 de
3

O "não fazer nada" realmente não funciona?

se por // Return Nothing você realmente quer dizer return null então escreva

return Source;

se você quer dizer, ignore o codepath e depois escreva

 if ( Source != null )
            {
                return Source;
            }
// source is null so continue on.

E por último

 if ( Source != value )
            { Source = value;
                RaisePropertyChanged ( "Source" );
            }

// nothing done.
Vinnyq12
fonte
3

O operador ternário RETORNA um de dois valores. Ou pode executar uma das duas instruções com base em sua condição, mas geralmente não é uma boa ideia, pois pode levar a efeitos colaterais indesejados.

bar ? () : baz();

Nesse caso, o () não faz nada, enquanto baz faz algo. Mas você apenas deixou o código menos claro. Eu escolheria um código mais detalhado, mais claro e fácil de manter.

Além disso, isso faz pouco sentido:

var foo = bar ? () : baz();

pois () não tem tipo de retorno (é nulo) e baz tem um tipo de retorno que é desconhecido no ponto de chamada neste exemplo. Se eles não concordarem, o compilador reclamará em voz alta.

Mike Hofer
fonte
2

Se você está preocupado com a verbosidade do seu código, eu escreveria isso em vez de tentar abusar das expressões.

if (Source == value) return;
Source = value;
RaisePropertyChanged("Source");
ChaosPandion
fonte
Não estou abusando de expressões, só estou pensando!
Ahmed Ghoneim
1

o?: é o operador de itinerário. (acredito que soletrei corretamente) e é simples de usar. como em um predicado booleano? iftrue: ifalse; Mas você deve ter um rvalue / lvalue como em rvalue = predicate? iftrue: iffalse;

ex int i = x < 7 ? x : 7;

se x fosse menor que 7, eu receberia a atribuição de x, caso contrário, seria 7.

você também pode usá-lo em uma devolução, como em return x < 7 ? x : 7;

novamente, como acima, isso teria o mesmo efeito.

então, Source = Source == value ? Source : string.Empty;eu acredito que é o que você está tentando alcançar.

johnathan
fonte
6
Eu gosto disso. O operador de itinerário : ajuda você a ir de A a B ... ou de A a C ... dependendo de A.
Rick Sladkey 01 de
Sim, ele quer dizer ternário. Mas o nome correto é "condicional".
Erick G. Hagstrom
1

O ?:Operador retorna um de dois valores, dependendo do valor de uma expressão booleana.

Condition-Expression ? Expression1 : Expression2

Descubra aqui mais sobre o ?:operador, também conhecido como Operador Ternário:

Rudenaggar
fonte
0

Eu não acho que você pode ser um operador e deve retornar um ou outro. Não é a substituição da instrução if else, embora possa ser usada para isso em certos casos.

atbebtg
fonte