Tipos anuláveis
Tipos comuns por valor não possuem valor nulo. Por exemplo, um inteiro sem valor, armazena o valor "0", uma string, recebe o valor vazio (representado pela constante String.Empty). Porém, em situações específicas, é possível extrair vantagens no uso do valor nulo em tais tipos (Por exemplo, em inserção de dados em campos nullable no banco de dados).
A partir do C# 2.0, foi introduzido o conceito de tipos anuláveis, ou seja, tornar possível que tais tipos convivam com o valor "nulo", sendo este o primeiro uso do operador "?" que veremos por aqui.
int? variavel = null;
if (variavel == null)
// seu codigo
Operador Ternário
Esse também é bem popular. Ele não oferece uma funcionalidade diferenciada, mas sim uma economia de código, uma estrutura diferente em termos de sintaxe. A idéia é simples: As vezes é necessário realizar decisões simples, que são resolvidas através de "if". Porém a utilização do operador ternário, pode economizar algumas linhas de código.
int a = 1;
int b;
b = (a == 1) ? a : 10;
Seu equivalente utilizando a estrutura “if” seria:
if (a == 1)
{
b = a;
}
else
{
b = 10
}
Portanto a sintaxe do operador ternário é:
Variável = (condição) ? valor caso true : valor caso false
Coalesce Operator
Sim, o nome está em inglês porque nunca vi o termo em português, então não inventar por aqui :P Acredito que dos três operadores com “Question Mark” (“?”), esse é o menos “famoso”, porém de uso também simples. A idéia é diminuir a quantidade de código para verificações com o objetivo de descobrir se o valor é nulo ou não. Ele também pode ser fácilmente substituído pelo uso de “Ifs”.
int? a = null;
int b;
b = a ?? 10;
Seu equivalente seria:
if (a == null)
b = 10;
else
b = (int) a;
Repare que, apesar da mesma funcionalidade, utilizando a estrutura de “IF”, já surge a preocupação da conversão dos tipos (no caso de um inteiro anulável e um inteiro).
Discussão
Um esforço antigo da engenharia de software é tornar o código cada vez mais “legível” a humanos, ou seja, torná-lo simples, de fácil entendimento. Exatamente por isso, existe uma resistência ao uso dos operadores descritos acima, justamente porque eles viriam a tornar mais “obscuro” o código do que se utilizassem estruturas simples de decisão. A minha opinião particular é que, partindo do pressuposto que programadores devem conhecer a sintaxe da linguagem utilizada, não acredito que o uso de tais operadores seja prejudicial, na verdade, devido à redução do número de linhas de código dentro do método que usa os tais operadores, acredito que se perca menos tempo tentando entender lógicas obtusas de comparações, se dando o luxo de prestar mais atenção as regras de negócio. E vocês? A discussão está em aberto :-)