- Structs em C# - diversão garantida
- Rápida introdução à Value Types vs Reference Types
- Inicialização de campos em estruturas
- Comportamento de construtores em estruturas.
- Outros cenários em que o comportamento de construtores em estruturas podem te surpreender.
- Argumentos default em construtores de estruturas (você ainda não esta confuso ?). (este post)
- Modificador
required
do C# 11 não vai salvar seuc*trabalho. - Estruturas usadas como valor default de argumentos.
- Bonus: Evolução das estruturas em C#.
Nos posts anteriores vimos que, em alguns cenários, o compilador C# pode não emitir invocaçcões de construtores de estruturas. Infelizmente a experiência com construtores em structs, pelo menos na minha opinião, pode ficar ainda mais confusa.
Para ilustrar esse ponto, suponha que você tenha o seguinte código:
Print(new S2());
Print(new S2(13));
void Print(S2 s) => System.Console.WriteLine(s.v);
struct S2
{
public int v;
public S2(int i = 42) => v = i;
public S2() => v = 84;
}
Qual resultado você espera observar ao compilar/executar o mesmo? 1
- O compilador emitirá um erro informando que
new S2()
representa uma chamada ambígua. - Ele compila e gera 42, 13.
- Ele compila e gera 84, 13.
A resposta correta, que pode surpreender alguns desenvolvedores, é que o programa compila com sucesso e imprime 84
e 13
(ou seja, a terceira opção).
Isso acontece porque na linha 1 o compilador C# vê o construtor sem parâmetros como uma melhor correspondência (best match) que aquele com o valor do parâmetro default, descartando as opções 1 e 21. O lado bom é que mesmo não sendo totalmente óbvio, pelo menos este comportamento é consistente entre classes/estruturas,
No entanto, o comportamento de construtores com relação à estruturas pode ficar ainda mais complexo/confuso; imagine que você tem exatamente o mesmo código acima, com a única diferença sendo a remoção do construtor sem parâmetros:
Print(new S2());
Print(new S2(13));
void Print(S2 s) => System.Console.WriteLine(s.v);
struct S2
{
public int v;
public S2(int i = 42) => v = i;
}
agora, com certeza o mesmo vai imprimir 42
e 13
, certo?
Não! Neste cenário, diferentemente das classes, um construtor com valores padrão para todos os seus parâmetros não é invocado, mesmo em expressões new
explícitas2 o que significa que o código acima irá imprimir 0
e 13
3.
Na próxima postagem, daremos uma olhada rápida em uma funcionalide do C# 11 conhecida como required members4 como uma forma de ajudar a identificar cenários nos quais nenhum construtor é invocado.
Como sempre, todo feedback é bem-vindo.
Divirta-se!
-
Para ser justo, o comportamento aqui é consistente com o de classes.↩↩
-
A especificação de construtores sem parâmetros em estruturas afirma explicitamente que esse comportamento é o mesmo das versões anteriores do C#.↩
-
Isso acontece porque a linha #1 é equivalente a
Print(default(S2))
; para obter mais detalhes, consulte esta postagem.↩ -
Estou ciente de que este não é o uso pretendido deste recurso, contudo o mesmo pode ser usado para sinalizar algumas instanciações de estruturas que não invocam um construtor.↩
No comments:
Post a Comment