C#  -  Novidades da versão 7 - II


 Neste artigo vou apresentar as novidades da versão 7.x da linguagem C#.

Continuando o artigo anterior vou concluir a apresentação das novidadades do C# 7.x.

Tuplas

Tuplas permitem combinar objetos de diferentes tipos. Antes do C# 7, as tuplas já faziam parte do .NET Framework com a classe Tuple. Os membros da tupla podem ser acessados com Item1, Item2, Item3, e assim por diante. No C# 7, as tuplas fazem parte da linguagem C# e você pode definir os nomes dos membros.

Assim, embora as tuplas estivessem disponíveis antes do C# 7.0, elas eram ineficientes e não tinham nenhum suporte de linguagem. Isso significava que os elementos de tupla só podiam ser referenciados como Item1, Item2 e assim por diante.

O C# 7.0 introduz o suporte de linguagem para tuplas, que permite nomes semânticos para os campos de uma tupla, usando tipos de tupla novos e mais eficientes.

var t1 = Tuple.Create(42, "teste");
int i1 = t1.Item1;
string s1 = t1.Item2;
 var t1 = (n: 42, s: teste");
 int i1 = t1.n;
 string s1 = t1.s;

 
C# 6.0 C# 7.0

Em uma atribuição de tupla, você também pode especificar os nomes dos campos no lado direito da atribuição:    var alfabeto = (Alfa: "a", Beta: "b");

Os novos recursos de tuplas exigem os tipos ValueTuple. Você deve adicionar o pacote NuGet System.ValueTuple para usá-lo em plataformas que não incluem os tipos.

Nomes de Tuplas inferidas

O C# 7.1 estende as tuplas inferindo automaticamente os nomes das tuplas, semelhantes aos tipos anônimos. Com o C# 7.0, os membros da tupla sempre precisam ser nomeados.

Caso o membro da tupla tenha o mesmo nome da propriedade ou campo que você atribui a ele, com o C# 7.1, se o nome não for fornecido, ele terá o mesmo nome que o membro designado:

  var t1 = (Nome: corredor.Nome, Vencedor: corredor.Vencedor);
  int vencedor = t1.Vencedor;
  C# 7.0  
  var t1 = (corredor.Nome, corredor.Vencedor);
  int wins = t1.Vencedor;
  C# 7.1 

Deconstructors

Não, isso não é um erro de digitação. Os desconstrutores não são destructors.

Basicamente, o que um Construtor faz é criar um novo objeto de determinado tipo com determinados parâmetros (aqui estou optando pelo construtor padrão, pois não possui parâmetros).

Então, o que o Desconstrutor deve fazer é desconstruir o objeto de volta às suas partes originais.

Para ser específico, você tem o controle de especificar como você gostaria que o objeto fosse desconstruído.

public class Aluno
{
    public string Nome { get; }
    public string Email { get; }


    public aluno(string nome, string email)
    {
        Nome = nome;
        Email = email;
    }

    public void Deconstruct(out string nome, out string email)
    {
         nome = Nome;
         email = Email;
    }
}
C# 7.0

Correspondência de Padrões

Com a correspondência de padrões, o operador is e a instrução switch foram aprimoradas com três tipos de padrões: o padrão const, o padrão de type e o padrão var.

O trecho de código abaixo à esquerda mostra padrões com o operador is.

  1. A primeira verificação de um padrão corresponde à constante 42,
  2. a segunda verifica se há uma objeto Pessoa
  3. e a terceira correspondência verifica cada objeto com o padrão var.

Usando o padrão type e o padrão var, uma variável pode ser declarada para acesso fortemente tipado:

public void PadroesComOperadorIs(object o)
{
     if (o is 42)
     {
     }

     if (o is Pessoa p)
     {
     }

     if (o is var v1)
     {
     }
}
public void PadroesComOperadorSwitch(object o)
{
    swtich (o)
    {
       case 42:
          break;
       case Pessoa p when p.Nome == "Macoratti":
          break;
       case Pessoa p:
         break;
       case var v:
         break;
     }
}
C# 7.0 C# 7.0

Acima à direita temos um exemplo usando a instrução switch, você pode usar os mesmos padrões com a cláusula case, e , também pode declarar uma variável para ser fortemente tipada caso o padrão corresponda; além disso você pode usar when para filtrar o padrão em um condição:

Throw Exceptions

O lançamento de exceções somente era possível com uma instrução; não era possível em uma expressão. Assim, quando você recebia um parâmetro com um construtor, verificações extras para null eram necessárias para lançar um ArgumentNullException.

Com o C# 7, as exceções podem ser lançadas em expressões, portanto, é possível lançar o ArgumentNullException quando o lado esquerdo for nulo - usando o operador de coalescência.

private readonly ILivrosService _livrosService;

public LivroController(LivrosService livrosService)
{
   if (livrosService == null)
   {  
      throw new ArgumentNullException(nameof(b));
   }
   _livrosService = livrosService;
}
C# 6.0
private readonly ILivrosService _livrosService;

public LivroController(LivrosService livrosService)
{
   _livrosService = livrosService ?? throw new ArgumentNullException(nameof(b));
}
C# 7.0

Com o C# 7.2, agora é permitido ter argumentos nomeados também após os posicionados. Esse recurso é chamado de : argumentos nomeados sem rastreio.

Async Main

Antes do C# 7.1, o método Main sempre precisava ser declarado do tipo void. Com o C # 7.1, o método Main também pode ser do tipo Task e usar as palavras-chave async e await:

static void Main()
{
        Metodo1Async().Wait();
}
async static Task Main()
{
    await MetodoAsync();
}
C# 7.0 C#   7.1                                                                      

Semântica de Referência

O .NET Core tem um grande foco em melhorar o desempenho. Adições aos recursos do C# para semântica de referência ajudam a aumentar o desempenho.

Antes do C# 7, a palavra-chave ref poderia ser usada com parâmetros para passar tipos de valor por referência.

Agora também é possível usar a palavra-chave ref com o tipo de retorno e com variáveis locais.

O trecho de código a seguir declara o método GetNumero para retornar uma referência a um int.

Desta forma, o chamador tem acesso direto ao elemento na matriz e pode alterar seu conteúdo:

int[] _numeros= { 3, 7, 11, 15, 21 };

public ref int GetNumero(int index)
{
    return ref _numeros[index];
}
C# 7.0

Com o C# 7.2, o modificador readonly pode ser adicionado aos retornos ref. Desta forma, o chamador não pode alterar o conteúdo do valor retornado, mas a semântica de referência é usada, e uma cópia do tipo de valor quando retornando o resultado pode ser evitado.

O chamador recebe uma referência, mas não pode alterá-lo:

int[] _numeros= { 3, 7, 11, 15, 21 };

public ref readonly int GetNumero(int index)
{
    return ref _numeros[index];
}
C# 7.2

Antes do C# 7.2, o C# poderia criar tipos de referência (uma classe) e tipos de valor (uma estrutura). No entanto, a estrutura também poderia ser armazenada na heap quando o boxing tivesse ocorrido.

Com o C# 7.2, um tipo pode ser declarado como sendo somente permitido na pilha: ref struct:

ref struct SomenteOnTheStack
{
}
C# 7.2

Concluimos assim a apresentação das novidades principais da versão 7.0, 7.1 e 7.2 da linguagem C#.

Em breve estarei detalhando cada uma das novidades com mais exemplos práticos.

"Não pergunteis, pois, que haveis de comer, ou que haveis de beber, e não andeis inquietos."
"Porque as nações do mundo buscam todas essas coisas; mas vosso Pai sabe que precisais delas."
"Buscai antes o reino de Deus, e todas estas coisas vos serão acrescentadas."
Lucas 12:29-31

Veja os Destaques e novidades do SUPER DVD Visual Basic (sempre atualizado) : clique e confira !

Quer migrar para o VB .NET ?

Quer aprender C# ??

Quer aprender os conceitos da Programação Orientada a objetos ?

Quer aprender o gerar relatórios com o ReportViewer no VS 2013 ?

Quer aprender a criar aplicações Web Dinâmicas usando a ASP .NET MVC 5 ?

 

  Gostou ?   Compartilhe no Facebook   Compartilhe no Twitter

 

Referências:


José Carlos Macoratti