Aug 31, 2023

Structs em C# - diversão garantida - Parte 3/9: Inicialização de campos em structs

Read this post in English

Lisez cet post en french.

  1. Structs em C# - diversão garantida
  2. Rápida introdução à Value Types vs Reference Types.
  3. Inicialização de campos em estruturas (este post).
  4. Comportamento de construtores em estruturas.
  5. Outros cenários em que o comportamento de construtores em estruturas podem te surpreender.
  6. Argumentos default  em construtores de estruturas (você ainda não esta confuso ?).
  7. Modificador `required` do C# 11 não vai salvar seu c* trabalho.
  8. Estruturas usadas como valor default de argumentos.
  9. Bonus: Evolução das estruturas em C#. 

Continuando com nossa série sobre Value Types, dado o código abaixo, o que você espera que ele imprima (recomendo tentar responder antes de executá-lo):

Se você respondeu 0 (zero), acertou em cheio e provavelmente já possui um bom entendimento de como .NET/C# lida com instanciação/inicialização de campos de value types.; por outro lado, se você respondeu 32 provavelmente você foi levado ao engano. 

Neste post discutirei brevemente um dos aspectos responsáveis por esse comportamento: inicialização de campos em .NET, ou para ser mais preciso, em C#.

De uma forma simplificada, sempre que o compilador C# encontra a inicialização de um campo o mesmo simplesmente move o código de inicialização para os construtores, ou seja, inicializar um campo é equivalente a definir seu valor nos construtores (campos estáticos são inicializados em construtores estáticos), portanto, dado o código abaixo:

o compilador C# irá processá-lo como se o mesmo fosse escrito como:
o  que pode ser confirmado no código
IL gerado abaixo contudo,  caso não esteja familiarizado com código IL, tenha o seguinte em mente:

  • Não se deixe assustar com sua aparente complexidade.
  • Incluí comentários para enfatizar as partes principais.
  • Detalhes menos imporatntes foram omitidos.
  • Não é necessário compreender todos os detalhes para entender o conceito principal.

As linhas 6~22 e 25~36 definem, respectivamente, um construtor sem parâmetros e um que recebe um número inteiro; observe que o código relacionado à inicialização do campo (`f = 42`) foi introduzido em ambos (linhas 9~11 e 29~31).

No próximo post começaremos a explorar o comportamento de construtores em  estruturas (struct), também conhecido como a segunda parte do quebra-cabeça que explica por que o programa no topo do post imprime 0.

Como sempre, todo feedback é bem vindo.

Divirta-se!

Structs in C# are fun - Part 3/9: Field initialization in structs

Leia este post em português

Lisez cet post en french.

  1. Structs in C# are fun.
  2. Brief introduction to Value Types vs Reference Types.
  3. Field initialization in structs (this post).
  4. Constructors and struct behavior.
  5. Other scenarios in which struct constructors behavior may surprise you.
  6. Struct with default argument values in constructors, a.k.a, are you not confused yet?
  7. `required` feature from C# 11 will not save your a** job.
  8. Struct used as default argument values.
  9. Bonus: Struct evolution in C#.

Continuing with our series on Value Types, given the code below, what do you expect it to print (I recommend trying to answer without running it first):

If you answered 0 (zero) you nailed it and probably already have a good understanding of how .NET/C# handles value type instantiation / field initialization; by the other hand, if you answered 32 you may have been tricked.

In this post I'll briefly discuss one of the aspects that leads to this behavior: field initialization in .NET, or to be more precise, in C#.

In an oversimplified way, whenever C# compiler finds a field initialization it will simply move the initialization code to the constructors, i.e, initializing a field is equivalent to setting its value in the constructors (static fields are initialized in static constructors), so given the code below:

the C# compiler will process it as it was written as:

which you can confirm in the generated IL below, but keep the following in mind if you're not familiar with IL code:

  1. There's no need to be daunted by its apparent complexity.
  2. I've included comments to emphasize the key parts.
  3. I've omitted certain less crucial specifics.
  4. Grasping all the details isn't important to understand the main concept.

Lines 6~22 and 25~36 defines, respectively, the constructor taking no parameters and the one taking an integer;  note that the code related to field initialization (`f = 42`) has been introduced in both (lines 9~11 and 29~31).

In the next post we'll start exploring struct constructor behavior, a.k.a, the second part of the puzzle that explains why the program at the top of the post prints 0.

As always, all feedback is welcome.

Have fun!

Les structures en C# sont amusantes - Partie 3/9: Initialisation des champs dans les structures

Leia este post em português

Read this post in English.

  1. Les structures en C# sont amusantes
  2. Brève introduction aux Value Types vs Reference Types.
  3. Initialisation des champs dans les structures (cet post).
  4. Comportement des constructeurs dans structures.
  5. Des autres scénarios dans lesquels le comportement des constructeurs de structure peut vous surprendre.
  6. Struct avec des valeurs d'argument par défaut dans les constructeurs, ou, n'êtes-vous pas encore confus ?
  7. Le modificateur `required`de C # 11 ne sauvegardera pas votre c*l emploi.
  8. Structure utilisée comme valeurs d'argument défaut.
  9. Bonus: L'evolution des structures en C#.

Poursuivant notre série sur les types de valeur (Value Types), étant donné le code ci-dessous, qu'attendez-vous qu'il imprime (je vous recommande d'essayer de répondre avant de l'exécuter):

Si vous avez répondu 0 (zéro), vous l'avez cloué et avez probablement déjà une bonne compréhension de la façon dont .NET/C# gère l'instanciation de type valeur/l'initialisation de champ; par contre, si vous avez répondu 32, vous avez peut-être été trompé.

Dans cet article, je vais aborder brièvement l'un des aspects qui conduisent à ce comportement : l'initialisation des champs en .NET, ou pour être plus précis, en C#.

D'une manière trop simpliste, chaque fois que le compilateur C# trouve une initialisation de champ, il déplacera simplement le code d'initialisation vers les constructeurs, c'est-à-dire que l'initialisation d'un champ équivaut à définir sa valeur dans les constructeurs (les champs statiques sont initialisés dans les constructeurs statiques), donc étant donné le code ci-dessous :

le compilateur C# le traitera tel qu'il a été écrit ainsi :

ce que vous pouvez confirmer dans l'IL généré ci-dessous, mais gardez ce qui suit à l'esprit si vous n'êtes pas familier avec le code IL :

  1. Il ne faut pas se laisser intimider par son apparente complexité.
  2. J'ai inclus des commentaires pour souligner les éléments clés.
  3. J'ai omis certains détails moins cruciaux.
  4. Il n’est pas nécessaire de saisir tous les détails pour comprendre le concept principal.

Les lignes 6~22 et 25~36 définissent le constructeur ne prenant aucun paramètre et celui prenant un int (Int32); notez que le code lié à l'initialisation du champ (`f = 42`) a été introduit dans les deux (lignes 9~11 et 29~31).

Dans le prochain article, nous commencerons à explorer le comportement du constructeur de structure, c'est-à-dire la deuxième partie du puzzle qui explique pourquoi le programme en haut de l'article imprime 0.

Comme toujours, tous les commentaires sont bienvenus.

Amuse toi!