Precedência estranho operador com ?? (operador de coalescência nulo)

Recentemente eu tive um bug estranho onde eu estava concatenando uma string com um int? e depois adicionando outra string depois disso.

Meu código era basicamente o equivalente a isso:

 int? x=10; string s = "foo" + x ?? 0 + "bar"; 

Por incrível que pareça, isso irá rodar e compilar sem avisos ou erros de tipo incompatíveis, assim:

 int? x=10; string s = "foo" + x ?? "0" + "bar"; 

E isso resulta em um erro inesperado de incompatibilidade de tipo:

 int? x=10; string s = "foo" + x ?? 0 + 12; 

Assim como este exemplo mais simples:

 int? x=10; string s = "foo" + x ?? 0; 

Alguém pode explicar como isso funciona para mim?

O operador de coalescência nulo tem precedência muito baixa, então seu código está sendo interpretado como:

 int? x = 10; string s = ("foo" + x) ?? (0 + "bar"); 

Neste exemplo, ambas as expressões são strings, então ele compila, mas não faz o que você quer. Em seu próximo exemplo, o lado esquerdo do ?? operador é uma string, mas o lado direito é um inteiro, então não compila:

 int? x = 10; string s = ("foo" + x) ?? (0 + 12); // Error: Operator '??' cannot be applied to operands of type 'string' and 'int' 

A solução, claro, é adicionar parênteses:

 int? x = 10; string s = "foo" + (x ?? 0) + "bar"; 

O ?? O operador tem precedência menor que o operador + , então sua expressão realmente funciona como:

 string s = ("foo" + x) ?? (0 + "bar"); 

Primeiro, a string "foo" e o valor de string de x são concatenados, e se isso for null (o que não pode ser), o valor de string de 0 e a string "bar" são concatenados.