Exportar (0) Imprimir
Expandir Tudo
Expandir Minimizar

Uso de parâmetros Opcionais no Visual C# 4

Por Renato Haddad

Junho, 2012

JJ218324.060DE5057573180CEC6D227C6D3E2207(pt-br,MSDN.10).png

Neste artigo irei abordar a declaração e o uso de parâmetros opcionais no Visual C# 4. Tenho visto muitos desenvolvedores criando códigos com assinaturas de métodos para fazer a mesma coisa, muitas vezes criando sobrecarga de métodos simplesmente porque não conhece o uso de parâmetros opcionais no C# 4.

Vale comentar que esta funcionalidade finalmente foi implementada na versão 4.0 do C# e os desenvolvedores VB.NET já tinham disponíveis desde a primeira versão em 2001. A explicação desta implementação no C# 4 é devido a um conjunto de novas funcionalidades como por exemplo, declaração de delegates e interoperabilidade com outras aplicações como Visual Studio Tools for Office (VSTO). Quem já precisou integrar o VSTO com C# sabe muito bem dos diversos parâmetros obrigatórios que no C# declarávamos com a palavra chave missing, e com os opcionais, isto tudo terminou.

Vamos aos exemplos. Crie um projeto de Console Application no VS 2010, linguagem C# é claro. Crie uma classe chamada CodDelegate contendo o código a seguir. O primeiro passo é declarar o delegate do tipo inteiro (int) chamado Operacao o qual contém dois argumentos, sendo a e b, ambos do tipo int. Este delegate irá criar um método assinado desta forma para ser consumido em qualquer parte do código.

 class CodDelegate
{
    delegate int Operacao(int a, int b);
}

Em seguida, declare o método Main como static void para que possamos invocar o delegate, conforme o seguinte código. Veja que é declarada uma variável chamada op que é do tipo Operacao. A seguir são declarados os dois parâmetros (a, b), assim como a atribuição da fórmula que o mesmo deverá executar, ou seja, o símbolo de atribuição (=>) diz que a fórmula irá somar a + b e o resultado será multiplicado por 3. Note que a fórmula é declarada na atribuição do delegate, pois não há nenhum método explícito, este será criado em tempo de execução.

E para consumir o delegate, basta invocar o op informando quais os respectivos valores, neste caso 2 e 4. Execute este código e veja que o resultado deverá ser 18 = (2 + 4) * 3.

class CodDelegate
{
    delegate int Operacao(int a, int b);

    static void Main(string[] args)
    {
        Operacao op = (a, b) => (a + b) * 3;

        Console.WriteLine(op(2,4));

        Console.ReadLine();
    }
}

Até aqui você é obrigado a declarar todos os argumentos, mas existem situações onde somente alguns são necessários. Portanto, neste mesmo código, substitua o delegate pelo seguinte código. Note que os parâmetros b e c contêm respectivos valores iniciais. Isto quer dizer que se você não informar o valor, será assumido o valor default declarado nesta assinatura.

delegate int Operacao(int a, int b = 4, int c = 7);

Outro passo a ser alterado é a declaração do Operacao, conforme a seguir.

Operacao op = (a, b, c) => (a + b + c) * 3;

Sendo assim, veja alguns exemplos de como passar alguns ou todos os valores dos parâmetros. Note ainda que o último código a seguir ilustra a passagem de apenas dois parâmetros, o primeiro e o terceiro. O segundo não é passado, então já sabemos que será assumido o valor padrão, no entanto, veja como deve ser a declaração do último parâmetro para pular o segundo. Na declaração use o nome da variável seguido de dois ponto e o valor.

Existe uma regra básica que diz que todo e qualquer parâmetro opcional deverá ser declarado por último na assinatura do método. Então, basta seguir esta regra que não irá errar. O que sugiro fortemente é que na execução destes códigos, use o Debug e inspecione os valores das variáveis durante a execução.

// passa o A
Console.WriteLine(op(2));
// passa o A / B
Console.WriteLine(op(2, 8));
// passa o A / B / C
Console.WriteLine(op(2, 14, 10));
// passa o A / C
Console.WriteLine(op(2, c: 10));

Agora vamos criar um novo delegate para calcular o imposto de renda de alguns funcionários. O primeiro passo é declarar o delegate conforme o código a seguir, contendo os parâmetros salario, percentual (perc) com valor padrão de 10 e o desconto com valor padrão de 80.

delegate decimal IR(decimal salario, decimal perc = 10, decimal desconto = 80);

Antes do Console.ReadLine adicione o código que contém a fórmula a ser aplicada no cálculo, sendo que se o salário for menor ou igual a 1000 (?), não paga-se imposto. Caso contrário ( : ) é aplicada a fórmula salário * (percentual / 100) – desconto. Claro que coloquei uma fórmula e valores hipotéticos, mas vale como exemplo.

IR imposto = (salario, perc, desconto)
    => (salario <= 1000) ?
        0 : salario * (perc / 100) - desconto;

E para ilustrar o uso deste delegate, monte diversos códigos como os a seguir, para simular a declaração de vários salários, percentuais e descontos. O único obrigatório é o salário, sendo que o percentual e o desconto podem ser opcionais porque tem o valor padrão.

Console.WriteLine(imposto(1000));
Console.WriteLine(imposto(5000, 5, 50));
Console.WriteLine(imposto(5000, 5));
Console.WriteLine(imposto(5000, desconto: 100));

No próximo exemplo vou mostrar como usar esta fórmula numa coleção de dados. O primeiro passo é criar uma nova classe chamada Funcionario contendo 3 propriedades (Nome, Salario e Sexo), conforme os tipos a seguir.

public class Funcionario
{
    public string Nome { get; set; }
    public decimal Salario { get; set; }
    public string Sexo { get; set; }
}

Para se criar uma coleção de funcionários é preciso usar o Generics. Neste caso usei o List<Funcionario> chamado lista contendo 3 funcionários com as respectivas propriedades.

var lista = new List<Funcionario>()
{
    new Funcionario{ Nome="Renato", 
        Salario=8000, Sexo="M" },
    new Funcionario{ Nome="Claudenir", 
        Salario=5000, Sexo="M" },
    new Funcionario{ Nome="Yara", 
        Salario=12000, Sexo="F"}
};

Para testar e visualizar o resultado monte um looping foreach para varrer toda a coleção chamada lista e mostrar cada funcionário com as devidas propriedades. Observe que durante o looping é que o imposto será calculado em função do salário.

foreach (var item in lista)
{
    Console.WriteLine(string.Format(
        "Nome: {0} - Salario: {1:n2} - IRT: {2:n2}",
        item.Nome, item.Salario,
        imposto(item.Salario)));
}

Já que temos uma lista de funcionários armazenados na coleção chamada lista, veja uma expressão Lambda para selecionar os nomes, os salários, calcular o imposto de renda (IRenda) e o Liquido. Aqui temos em IRenda e Liquido o que chamamos de tipo anônimo. O que isto significa? Se é anônimo significa que será criado em tempo de execução, o qual irá chamar o delegate imposto, passando o salário como argumento. O uso de expressão Lambda é fantástico porque nos permite criar e atribuir elementos que não existem, ou seja, anônimos.

var dados = lista.Select(
    f => new {
        f.Nome,
        f.Salario,
        IRenda = imposto(f.Salario),
        Liquido = f.Salario - imposto(f.Salario)
    });

Sendo assim, como ler os dados contidos na lista chamada dados? No código anterior é importante notar que dados foi declarado como var, ou seja, ele assume automaticamente o tipo de acordo com o que foi atribuído. Neste caso, dados será do tipo IEnumerable, o que nos permite ler apenas uma vez esta coleção. Se fosse declarado como IQueryable a lista poderia ser lida e manipulada quantas vezes fossem necessário. Para exibir os dados usei o string.Format que permite exibir os valores já formatados com duas casas decimais (:n2). Cabe ressaltar que o IRenda e o Liquido são Anonymous Types (anônimos).

foreach (var item in dados)
{
            Console.WriteLine(string.Format(
"Nome: {0} - Salario: {1:n2} - IR: {2:n2} - Liquido: {3:n2}",
item.Nome, item.Salario, item.IRenda, item.Liquido));
}

Concluindo, o uso de parâmetros opcionais nos ajuda muito na criação de métodos com valores padrão, e você pode preparar uma aplicação de forma que ela se comporte com um gerador de códigos. Em alguns casos vi desenvolvedores criarem os valores dos parâmetros opcionais em arquivos XML ou TXT, e no momento da carga, tais valores são lidos e atribuídos.

E, quando você for estudar e aplicar o Entity Framework, saiba que isto pode fazer uma boa diferença no desenho da aplicação. Outra dica que dou é estude expressões Lambda e LINQ (Language Integrated Query).

Mostrar:
© 2015 Microsoft