Já que true
não é um tipo de string, como é null + true
uma string?
string s = true; //Cannot implicitly convert type 'bool' to 'string'
bool b = null + true; //Cannot implicitly convert type 'string' to 'bool'
Qual é a razão por trás disso?
Respostas:
Por mais bizarro que possa parecer, é simplesmente seguir as regras das especificações da linguagem C #.
Da seção 7.3.4:
Então, vamos examinar isso por sua vez.
X é o tipo nulo aqui - ou não é um tipo, se você quiser pensar dessa forma. Não está fornecendo candidatos. Y is
bool
, que não fornece nenhum+
operador definido pelo usuário . Portanto, a primeira etapa não encontra operadores definidos pelo usuário.O compilador então segue para o segundo ponto, examinando as implementações de operador + binário predefinido e suas formas levantadas. Eles estão listados na seção 7.8.4 das especificações.
Se você examinar esses operadores predefinidos, o único aplicável é
string operator +(string x, object y)
. Portanto, o conjunto de candidatos tem uma única entrada. Isso torna o marcador final muito simples ... a resolução de sobrecarga seleciona esse operador, fornecendo um tipo de expressão geral destring
.Um ponto interessante é que isso ocorrerá mesmo se houver outros operadores definidos pelo usuário disponíveis nos tipos não mencionados. Por exemplo:
Tudo bem, mas não é usado para um literal nulo, porque o compilador não sabe o que fazer
Foo
. Ele só sabe que deve considerarstring
porque é um operador predefinido explicitamente listado na especificação. (Na verdade, é não um operador definido pelo tipo string ... 1 ) Isso significa que este não será compilado:Outros tipos de segundo operando usarão alguns outros operadores, é claro:
1 Você pode estar se perguntando por que não existe um operador string +. É uma pergunta razoável e estou apenas adivinhando a resposta, mas considere esta expressão:
Se
string
não houvesse nenhum caso especial no compilador C #, isso seria tão eficaz:Então isso criou duas strings intermediárias desnecessárias. No entanto, como há suporte especial dentro do compilador, ele é realmente capaz de compilar o acima como:
que pode criar apenas uma única string com o comprimento exato, copiando todos os dados exatamente uma vez. Agradável.
fonte
true
não ser conversível parastring
. Se a expressão fosse válida, o tipo seriastring
, mas, neste caso, a falha na conversão para string torna a expressão inteira um erro e, portanto, não tem tipo.x
é do tipostring
. Observe que a assinatura usada aqui éstring operator+(string, object)
- está convertendobool
paraobject
(o que é bom), não parastring
.A razão é porque, uma vez que você introduza
+
, as regras de vinculação do operador C # entram em ação. Ele considerará o conjunto de+
operadores disponíveis e selecionará a melhor sobrecarga. Um desses operadores é o seguinteEssa sobrecarga é compatível com os tipos de argumento na expressão
null + true
. Portanto, ele é selecionado como o operador e é avaliado essencialmente como((string)null) + true
aquele que avalia o valor"True"
.A seção 7.7.4 das especificações da linguagem C # contém os detalhes dessa resolução.
fonte
operator+
parastring
. Em vez disso, ele só existe na mente do compilador e simplesmente o traduz em chamadas parastring.Concat
O compilador sai em busca de um operador + () que pode receber um argumento nulo primeiro. Nenhum dos tipos de valor padrão se qualificam, nulo não é um valor válido para eles. A única correspondência é System.String.operator + (), não há ambigüidade.
O segundo argumento desse operador também é uma string. Isso é kapooey, não é possível converter bool em string implicitamente.
fonte
Curiosamente, usando o Reflector para inspecionar o que é gerado, o seguinte código:
é transformado nisso pelo compilador:
O raciocínio por trás dessa "otimização" é um pouco estranho, devo dizer, e não rima com a seleção de operador que eu esperava.
Além disso, o seguinte código:
é transformado em
onde,
string b = true;
na verdade, não é aceito pelo compilador.fonte
null
será convertido em string nula, e há um conversor implícito de bool para string, então otrue
será convertido para string e, em seguida,+
operador será aplicado: é como: string str = "" + true.ToString ();se você verificar com Ildasm:
string str = null + true;
é como abaixo:
fonte
Louco?? Não, deve haver uma razão por trás disso.
Alguém ligou
Eric Lippert
...fonte
A razão para isso é a conveniência (concatenar strings é uma tarefa comum).
Como BoltClock disse, o operador '+' é definido em tipos numéricos, strings, e pode ser definido para nossos próprios tipos também (sobrecarga de operador).
Se não houver um operador '+' sobrecarregado nos tipos do argumento e eles não forem tipos numéricos, o padrão do compilador é a concatenação de string.
O compilador insere uma chamada para
String.Concat(...)
quando você concatena usando '+', e a implementação de Concat chama ToString em cada objeto passado para ele.fonte