C# C# 9.0 – Inteiros nativos e inferência de tipos

Conheça os novos tipos de dados introduzidos no C# 9.0, os inteiros nativos e os novos recursos da inferência de tipos.

Wladimilson M. Nascimento 15 de dezembro de 2020

Finalizando a nossa série de posts sobre os novos recursos do C# 9.0. Neste artigo veremos dois novos recursos: inteiros nativos e melhorias na inferência de tipos.

Inteiros nativos

Aplicações que processam muitas operações matemáticas e precisam garantir que essas operações utilizem o máximo que o processador pode fornecer, agora podem fazer uso dos inteiros nativos.

Inteiros nativos são dois novos tipos de dados representados pelas cláusulas nint e nuint. Nos bastidores elas são alias, respectivamente, dos tipos System.IntPtr and System.UIntPtr.

Em tempo de desenvolvimento não há diferença entre os tipos int e nint:

int defaultInt = 55;
nint nativeInt = 55;

Entretanto, durante a execução da aplicação, se o computador for 32 bits, o nint se comportará como um inteiro de 32bits. Se ele for 64bits, o tipo de comportará como um inteiro de 64 bits.

Para garantir que não haverá perda de dados, pode ser utilizado as constantes int.MinValue e int.MaxValue para verificar o limite inferior e superior de valores.

Melhorias na inferência de tipos

Chamado de target typing, a inferência de tipos é o processo onde o compilador infere o tipo de dado pelo contexto da expressão. Por exemplo:

var nome = "Treinaweb";

Na expressão acima, o compilador sabe que nome é uma variável string, pois está sendo atribuído à ela uma string.

Quando este tipo não pode ser inferido, o tipo da variável deve ser especificado:

string nome = null;

Pelo fato da variável nome, na expressão acima, receber o valor null, o seu tipo é especificado.

Antes do C# 9.0, a inferência de tipos era realizada fazendo o uso da cláusula var, limitando seus benefícios as declarações das variáveis/objetos. Agora na nova versão da linguagem, este recurso foi estendido a cláusula new.

Inferência de tipos em “expressões new”

No C#, a sintaxe para declarar um novo objeto é new T(), sendo T o tipo do objeto que está sendo instanciado. No C# 9.0, caso este tipo já estiver sendo especificado, ele pode ser omitido da expressão new:

Pessoa pessoa = new();

O compilador saberá qual construtor invocado baseado no tipo do objeto. Se este construtor receber algum parâmetro, este deve ser informado:

Pessoa pessoa = new("Carlos");

Como o tipo do objeto precisa ser especificado na expressão, não é possível utilizar esta nova cláusula new com a cláusula var:

var pessoa = new("Carlos");//Será gerado um erro

Quando houver sobrecarga de construtor e/ou parâmetros opcionais?

Mesmo omitindo o tipo, o new funciona da mesma forma que antes. Assim, mesmo se a classe declarar uma sobrecarga de construtor:

class Pessoa {
  public string Nome { get; set; }

  public Pessoa() {}

  public Pessoa(string nome) {
    Nome = nome;
  }
}

O compilador saberá qual chamar de acordo com os parâmetros informados:

Pessoa pessoa1 = new();
Pessoa pessoa2 = new("Thomas");

Isso também ocorre se o construtor possuir parâmetros opcionais:

class Pessoa {
  public string Nome { get; set; }
  public string Tratamento { get; set; }

  public Pessoa(string nome = null, string tratamento = null) {
    Nome = nome;
    Tratamento = tratamento;
  }
}
Pessoa pessoa1 = new("Thomas");
Pessoa pessoa2 = new("Carlos", "Sr.");

E também pode-se fazer uso de parâmetros nomeados:

Pessoa pessoa3 = new(tratamento: "Sra.", nome:"Maria");

Porque usar o new se já há o var?

Se nos limitarmos apenas as declarações dos objetos. Uma expressão com o new:

Pessoa pessoa = new("Thomas");

E uma expressão com o var:

var pessoa = new Pessoa("Thomas");

Irão gerar o mesmo código intermediário. Então nessa situação, o uso de um ou de outro irá depender das preferências do desenvolvedor. Nenhuma das duas expressões irá tornar o código mais ou menos performático.

Entretanto, em situações onde o uso do var não é possível e é que a nova expressão new brilha, como na inicialização das propriedades de uma classe:

public class Curso
{
    public Curso()
    {
        Alunos = new();
    }
    public List<Person> Alunos { get; }
}

O código acima poderia ser resumido para:

public class Curso
{
    public List<Person> Alunos { get; } = new();
}

Melhorando ainda mais a sua legibilidade.

Conclusão

A nona versão do C# trouxe uma leva de novos recursos que visam principalmente melhorar a legibilidade do código e facilitar a vida do desenvolvedor. Assim como ocorre sempre, esses recursos serão adotados aos poucos, conforme novos projetos sejam criados e os antigos sejam migrados para esta nova versão da linguagem.

Então, caso não tenha visto os dois primeiros artigos desta série, recomendo que volte e veja como trabalhar com propriedades init e record e programas top-level e os novos recursos do pattern matching.

Por hoje é só. Até a próxima.

Deixe seu comentário

Conheça o autor desse artigo

  • Foto Autor Wladimilson M. Nascimento
    Wladimilson M. Nascimento

    Instrutor, nerd, cinéfilo e desenvolvedor nas horas vagas. Graduado em Ciências da Computação pela Universidade Metodista de São Paulo.

    Posts desse Autor

Artigos relacionados