Fala Filhotes! Hoje vou mostrar mais uma utilidade dessa nossa versátil ferramenta. É a criação de Testes de unidade! Não sabe o que é um Teste de unidade? Bom… é um teste simples que tem como objetivo validar os dados de entrada e saída de um método, classe ou ate mesmo um objeto. Resumindo: É um teste para verificar que seu método ( no nosso caso ) está retornando o que ele deveria retornar.
Estou usando o Visual Studio 2010 mas o 2008 também possui essa ferramenta. Vamos ao exemplo então: Tenho um projeto de nome BOL dentro da minha solution com uma classe de nome Employee. Segue a classe abaixo:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace BOL
{
///
/// Classe Empregado (didático)
///
public class Employee
{
#region Enums
///
/// Enum com a função do empregado
///
public enum Role
{
Faxineiro,
Gerente,
Diretor
}
#endregion
#region Propriedades
public int codEmployee { get; set; }
public string NameEmployee { get; set; }
public Role RoleEmployee { get; set; }
public double Salary { get; set; }
///
/// Retorna a hora extra, que é o salario dividido por 28 vezes 1.5
///
public double HoraExtra
{
get { return (Salary / 28 * 1.5); }
}
#endregion
#region Construtores
public Employee()
{
}
#endregion
#region Metodos Estaticos
///
/// Verifica se o salario do empregado esta adequado com o do mercado
///
/// Retorna True se esta e False se não
public static bool CheckSalary(Employee empregado)
{
//
// Checa qual o emprego do empregado
// Para verificar se o salario é compativel com o do mercado
//
switch (empregado.RoleEmployee)
{
case Role.Faxineiro:
if (empregado.Salary > 700)
return true;
break;
case Role.Gerente:
if (empregado.Salary > 2600)
return true;
break;
case Role.Diretor:
if (empregado.Salary > 4000)
return true;
break;
}
return false;
}
///
/// Quanto o empregado recebe em 7 dias de serviço
///
/// Objeto do tipo Employee
public static double GetWeeklyPayment(Employee empregado)
{
var total = empregado.HoraExtra * 7;
//
// Retorna o valor total
//
return total;
}
#endregion
}
}
Como você podem ver essa é uma classe simples com 2 métodos estáticos, uma propriedade só de leitura ( Hora Extra ) e o resto de propriedades normais.
Então agora nós iremos criar os testes para esses dois métodos e para nossa propriedade “Hora Extra”.
Mas como isso? Basta clicar em algum lugar dentro da classe Employee e depois em “Create Unit Tests”

Reparem que aparece uma nova tela mostrando os itens da sua classe. Nessa tela você escolhe os métodos/propriedades para quais serão criados os testes de unidade. Então vamos selecionar só os nossos métodos e nossa propriedade “Hora Extra”.
Veja que no Output project você tem a opção de criar um novo projeto de testes, ou se nós tivéssemos, poderíamos usar um projeto já existente. Podemos configurar como será gerado nossa classe de testes clicando em Settings:
Você pode ver que o nome do arquivo e da classe é por padrão o nome da sua classe mais a palavra Test, você pode mudar a nomenclatura da maneira que você quiser. Vamos ver o que cada opção faz:
Mark all test results Inconclusive by default – Se você não modificar os testes que serão gerados, eles iram retornar inconclusivo, isso é uma maneira de mostrar ao programador que ele tem que alterar o teste. (Será dado o exemplo mais abaixo)Enable generation warnings – De acordo com o site da MSDN essa função não está ativa.
Globally qualify all types – Gera as variáveis com o qualificador global ( [namespace].[variável] ) para evitar ambigüidade entre tipos.
Enable documentation comments – Habilita a geração dos comentários para cada método.
Honor InternalsVisibleTo Attribute – Se você marcar essa opção, os métodos marcados como Friend ou Internal serão tratados como métodos públicos.
Lembrando que se você estiver usando o Visual Studio 2008 ou 2005 as opções podem ter nomes diferentes, mas funcionalidades iguais ou parecidas.
Depois de escolher as opções basta apertar OK. E OK na tela de criar os testes.
Se você criou um novo projeto escolha um nome para ele e aperte em Create.
Você pode reparar que um novo projeto de testes foi criado na sua solution com uma classe com o nome que definimos mais acima. Também pode ver que ela criou os métodos de testes que você pediu. Vamos usar o método CheckSalaryTest como exemplo de como o método é:
///
///A test for CheckSalary
///
[TestMethod()]
public void CheckSalaryTest()
{
Employee empregado = null; // TODO: Initialize to an appropriate value
bool expected = false; // TODO: Initialize to an appropriate value
bool actual;
actual = Employee.CheckSalary(empregado);
Assert.AreEqual(expected, actual);
Assert.Inconclusive("Verify the correctness of this test method.");
}
Perceba os “//TODO ” o visual studio já marcou isso para você saber que você tem que inicializar a variável com algum valor, perceba que por padrão a variável esta nulo. Então nós temos que substituir isso pelo valor a ser testado:
Employee empregado = new Employee { NameEmployee = "Andre", Salary = 800, RoleEmployee = Employee.Role.Faxineiro };
Percebam que existe uma variável com o nome de “expected“ no nosso método de testes, o conteúdo dessa variável deve ser o valor que nós esperamos alcançar. Como assim? Bom, o método que nós vamos chamar não é o CheckSalary? Lembrando, o CheckSalary checa se o meu salário é adequado com o do mercado. Então se mandarmos esse nosso objeto, ele deveria retornar True já que o “André” é um faxineiro e ganha mais que o piso salarial (700) de acordo com o método. Então o valor da variável expected será True. Ótimo! Perceba que o resto do código é a simples execução do método e mais uma comparação do resultado obtido (actual) com o esperado (expected) mas espere, e aquele “Assert.Inconclusive” ? Lembra da configuração que fizemos mais cedo? Se você executar esse teste agora ele retornará como inconclusivo. Basta tirar essa linha e estaremos pronto para ir! Olha como ficou o nosso método depois de toda essa configuração:
///
///A test for CheckSalary
///
[TestMethod()]
public void CheckSalaryTest()
{
//
// Crio um novo empregado para fins de testes
//
Employee empregado = new Employee { NameEmployee = "Andre", Salary = 800, RoleEmployee = Employee.Role.Faxineiro };
//
// O resultado que esperamos é um true
//
bool expected = true;
bool actual;
actual = Employee.CheckSalary(empregado);
Assert.AreEqual(expected, actual);
}
Beleza, mas e agora? Como executamos isso? Vários jeitos... Podemos executar um de cada vez usando esse “botãozinho” ao lado de cada método:

Ou usamos os ícones na nossa toolbar para executar todos os testes de uma vez.
E depois de executar, é só conferir o resultado.
E se falhar:
Simplesmente aperte com o botão direito e “View Test Results Details” para abrir os detalhes juntamente com a exceção que aconteceu:
Existem outras ferramentas do Visual Studio para melhorar a qualidade dos testes, maior informação dos resultados e etc… Mas não pretendo falar sobre eles agora, senão o post iria ficar muito longo e confuso. Então por hoje é isso! E claro, você pode colocar esse projeto de testes no TFS também.
Então, nós vimos que graças ao Visual Studio podemos criar testes de unidade com “meia dúzia” de cliques, algo muito útil na vida de um desenvolvedor.
Espero que vocês tenham gostado, já vou seguir o meu caminho, até mais.
Edit: Alterado o nome de testes unitários para testes de unidade. Dica do @Camiloribeiro. Obrigado!
Faaalllaaaaaa Filhoteess! Cês tão bão?
Então, hoje eu vou começar a explicar algumas funcionalidades “Ocultas” da nossa principal ferramenta, o Visual Studio!
Como vocês sabem o Visual Studio tem uma cassetada varias funcionalidades que muitas vezes nós não usamos, não que elas sejam inúteis, longe disso, o fato é que nós não somos acostumados a usar algo mais do que o BUILD ou EXECUTE. Bom… vou mostrar para vocês 10 atalhos muito úteis que irão facilitar suas vidas!
F12 - Go to Definition
Leva o cursor para a origem do método/variável. Muito útil para quando você quer saber o que aquele método faz ou aonde você esta declarando aquela variável.
Ctrl + “–” e Ctrl + Shift + “-“ - Backward e Forward
Volta (Ctrl + “-”) o cursor para o ultimo lugar onde ele estava funciona igual aos botões de voltar e avançar do browser.
Ctrl + Shift + F9 – Delete all Breakpoints
Sabe quando você esta “atrás” de algum erro e enche de breakpoints o código, e quando você resolve o erro os breakpoints ainda estão lá? Então… Com esse atalho você deleta TODOS os breakpoints da solution.
Ctrl + M + M – Collapse
Você pode dar um collapse (recolhida) no método aonde você está, deixando–o como um bloco de código que pode ser expandindo novamente usando o mesmo atalho.
Alt + Enter – Open Properties
É só clicar em um projeto e apertar Alt + Enter para abrir as propriedades do mesmo, alias isso abre a propriedade de quase tudo no windows e isso funciona ate no windows explorer.
Ctrl + B + T – Bookmark
Adiciona / Remove a linha atual à uma espécie de “favoritos” aonde você pode navegar entre essas linhas pelos atalhos abaixo.
Ctrl + B + N e Ctrl + B + P – Next / Previous Bookmark
Navega entre os bookmarks, ótimo para quando você tem trechos do código que você sabe que você vai acabar tendo que voltar para terminar ou adicionar algo.
Shift + F12 – Find Usages
Esse atalho é excelente! Você usa esse atalho em cima de algum método/variável e aparece uma tela mostrando TODOS os lugares em seu código que você está invocando esse método.
Ctrl + K + C e Ctrl + K + U - Comment e Uncomment
Comenta (Ctrl + K + C) e “descomenta” (Ctrl + K + U) as linhas selecionadas. Muito útil quando você acostuma.
Ctrl + K + D e Ctrl + K + F - Reformat Document / Code Block
Sabe quando o seu código vai ficando desorganizado a medida que você vai codificando? Então, seus problemas acabaram! Pois com esses atalhos você formata todo o código ( Ctrl + K + D) ou só uma parte (Ctrl + K + F) de uma vez!
A sim, esses atalhos foram testados nos Visual Studio 2008 e Visual Studio 2010, e sei que vários funcionam no Visual Studio 2005 também, mas não sei são todos.
Então é isso ai! Eu uso bastante esses atalhos e espero que vocês tenham encontrado algum atalho útil. Qualquer dúvida me avisem! Ate mais filhotes!
Eai filhotes, tudo bem?
Hoje vou mostrar como se cria indexadores! Não sabe o que é um Indexador? Um indexador basicamente deixa sua classe com um comportamento semelhante ao de um array, deixa eu dar um exemplo:
Você consegue acessar um item de um array/collection apenas passando o ID/KEY:
meuArray[1] = "teste";
O Indexador deixa nossa classe com esse comportamento. Então vamos ao que interessa!!
Para criar o indexador numa classe basta você criar a seguinte propriedade:
public TIPO this[int index]
{ ...
Aonde o TIPO é o tipo do objeto/retorno, e o parâmetro pode ser qualquer tipo (Int, String, …) e ate mais de um (para matrizes ou etc…) , no nosso caso usaremos um inteiro para pegar o índice.
Criei duas classes para dar um exemplo:
///
/// Propriedades Genéricas
///
public class GenericProperty
{
public enum DbType
{
Varchar,
Int,
Bit
}
public GenericProperty()
{
}
public string Name { get; set; }
public DbType Type { get; set; }
//Faço um Override no ToString para poder mostrar o Nome do campo e o tipo na hora de invocar o ToString.
public override string ToString()
{
return Name + " [" + Type + "]";
}
}
///
/// Classe com todas as propriedades genericas
///
public class PropertyControl
{
// Coleção com as propriedades genericas
private Collection<GenericProperty> colProp;
//Nosso INDEXER do tipo GenericProperty
public GenericProperty this[int index]
{
get { return colProp[index]; }
set { colProp[index] = value; }
}
//Método que adiciona o item à coleção
public void AddItem(GenericProperty newProp)
{
colProp.Add(newProp);
}
// Meu construtor tbm instancia a collection
public PropertyControl()
{
colProp = new Collection<GenericProperty>();
}
}
E pronto… como podemos ver abaixo, usamos nossa classe como uma array:
//Instanciamos nossa Classe
var ObjTeste = new PropertyControl();
// Adiciona os itens
// Usando as chaves "{" na hora de criar um novo objeto, eu posso setar as propriedades do mesmo, sem precisar de um construtor
ObjTeste.AddItem(new GenericProperty { Name = "Nome", Type = GenericProperty.DbType.Varchar });
ObjTeste.AddItem(new GenericProperty { Name = "Idade", Type = GenericProperty.DbType.Int });
// Alterando o valor pelo index, como se fosse uma collection normal
ObjTeste[0].Name = "Endereco";
// Jogo no label o valor do nosso objeto, que vai ser "Idade [Int]"
labelTeste.Text = ObjTeste[1].ToString();
Muito legal… Usando os indexadores nós temos a mesma comodidade de uma collection/array e também evitamos expor nossa collection, além de poder criar métodos de conversões no GET / SET do Indexador. E claro os Indexadores podem ser sobrecarregados.
Bom, espero que tenha ficado claro. Um bom dia para você e ate mais.
E para finalizar: pretendo estar mais presente no blog a partir de agora!
Fonte: http://msdn.microsoft.com/en-us/library/6x16t2tx.aspx
Update: Resolvido problemas no case-sensitive.
Fala Filhotes…
Hoje vou mostrar um “esqueminha” que apesar de não ser novidade (nenhuma) é bastante interessante do ASP.NET, mas primeiro vamos a uma pequena explicação sobre o funcionamento de paginas web.
Imagino que muitos de vocês devem ter aprendido isso na faculdade mas deixa eu fazer um resumão:
Muitos anos atrás quando a internet estava engatinhando, os servidores web usavam apenas arquivos simples como .html, mas a medida que o tempo passou as necessidades também aumentaram. Os programadores precisavam estender a capacidade dos servidores web de alguma forma. Então a Microsoft criou o ISAPI ( Internet Server API) e graças a isso conseguimos extender varias funcionalidades do IIS ( e outros servidores web que são compatíveis com o ISAPI ). Beleza!!! Mas e ai? Cumé qui esse trem funciona?
Bom filhote, é ate bem simples… Veja bem, o ISAPI consiste basicamente de dois componentes: Extensões e Filtros:
Extensões:
As extensões ISAPI são as aplicações que realmente rodam no IIS, e possuem acesso a todas as funcionalidades do IIS. As extensões podem ser implementadas usando DLLs.
As extensões ISAPI devem ser chamada para serem executadas, por exemplo, para chamar a extensão ISAPI usuariocadastro.dll você deve chamar a seguinte URL enviando também os valores que ela precisa via query string:
http://www.siteteste.com.br/usuariocadastro.dll?nome=Andre&idade=22&sexo=M&url=100loop.com.br/
Filtros:
Um filtro ISAPI é um … bom… filtro, entre o servidor web e o cliente. Ao contrario das extensões ISAPI que o usuário tem que chamar a URL para escuta-las, toda requisição para o servidor passa no filtro ISAPI e o próprio servidor passa a requisição para o filtro responsável. Um filtro ISAPI pode criar um log das requisições ou mesmo tratar / modificar alguma informação.
Requisições do ASP.NET
As requisições do ASP.NET são feitas de forma linear, a requisição é passada por todos os módulos, aonde cada um pode realizar qualquer tipo de ação sobre ela. Depois de passar por todos os módulos ela irá para um (apenas um) HTTP handler. O handler processa a requisição e o resultado será novamente enviado a todos os módulos.
Certo! Agora que entendemos um pouco mais sobre o funcionamento do ISAPI e ASP.NET, vamos ao que interessa!
HTTPHandlers
Então, como vimos um HTTPHandler é um código que executa quando uma requisição para um recurso especifico é feita pelo server. Você consegue interagir com a requisição e até enviar um novo retorno ao browser. Para criar um HTTP Handler, você precisa criar uma classe que implemente a interface IHttpHandler ( para um Handler síncrono) ou IHttpAsyncHandler ( para um handler assíncrono ) ou ate mesmo qualquer classe que implemente IHttpHandlerFactory. Você deve implementar a propriedade IsReusable e o método ProcessRequest para se usar o IHttpHandler e os métodos BeginProcessRequest e EndProcessRequest para o IHttpAsyncHandler . A propriedade IsReusable mostra quando o objeto IHttpHandlerFactory ( O objeto que chama o Handler correto ) vai pôr o Handler numa pool para o reutilizar depois ( aumentando a performance ) ou se vai criar uma nova instancia sempre que precisar dele de novo. O método ProcessRequest é o método chave, o que faz o processamento da requisição.
Beleza! Parece ser muito, muito complicado, mas na verdade é bem simples. Vamos ao exemplo!
Nesse exemplo criaremos um thumbnail, que por padrão SEMPRE encolherá a imagem, quer dizer, se o usuário acessar a imagem diretamente ( 100loop.com.br/imagem.jpg ) ele também à verá encolhida. Então, como eu vejo ela no tamanho original ou aumento o tamanho do thumbnail? bom, é só mandar o tamanho dela via Query String. Estranho? Mais ou menos, dê uma olhada no código:
Primeiro a nossa classe que herda do handler:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.SessionState;
using System.Configuration;
using System.Web.UI;
using System.Drawing;
using System.IO;
using System.Drawing.Imaging;
namespace HttpHandlers
{
public class HandlerLogin : IHttpHandler
{
///
/// Propriedade necessaria!
///
public bool IsReusable
{
get
{
return false;
}
}
///
/// Metodo que cria um thumbnail de uma imagem, calculando o tamanho para não perder as proporções
///
/// Local da imagem
/// Nova largura da imagem
/// Nova Altura da imagem
public Bitmap CreateThumbnail(string path, int parWidth, int parHeight)
{
// Nosso Bitmap de retorno
Bitmap bmpOutput = null;
try
{
// Nova bitmap para pegar o arquivo e suas medidas
Bitmap bitTemp = new Bitmap(path);
ImageFormat loFormat = bitTemp.RawFormat;
// Variavel para manter a proporção
decimal ratio;
int newWidth = 0;
int newHeight = 0;
// Se a Imagem for menor que o Thumbnail então retorna a imagem
if (bitTemp.Width < parWidth && bitTemp.Height < parHeight)
return bitTemp;
// Pega a proporção dividindo a largura pela altura
ratio = (decimal)bitTemp.Width / bitTemp.Height;
newHeight = parHeight;
newWidth = parWidth;
// Checa qual lado é maior para manter a proporção baseado nesse lado.
if (parHeight > parWidth)
{
decimal lnTemp = newHeight * ratio;
newWidth = (int)lnTemp;
}
else
{
decimal lnTemp = newWidth / ratio;
newHeight = (int)lnTemp;
}
// Cria o bitmap com as nossas medidas
bmpOutput = new Bitmap(newWidth, newHeight);
// Criamos um objeto do tipo Graphics para podermos "desenhar" a imagem no nosso output
Graphics newGraphic = Graphics.FromImage(bmpOutput);
// Setamos o InterpolationMode para HighQualityBicubic para não perdemos (ou perdemos menos ) qualidade
// na imagem na hora de encolhê-la. Claro, o tamanho do arquivo fica um pouco maior.
newGraphic.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;
// transformamos areas transparentes dos gifs em branco.
newGraphic.FillRectangle(Brushes.White, 0, 0, newWidth, newHeight);
// Desenhamos a nossa imagem ( q esta no temp ) com os novos tamanhos no output
newGraphic.DrawImage(bitTemp, 0, 0, newWidth, newHeight);
// Fechamos o temp
bitTemp.Dispose();
}
catch
{
return null;
}
// Retornamos a nossa imagem
return bmpOutput;
}
///
/// Metodo principal que irá executar quando uma imagem for chamada (método necessario!)
///
///
public void ProcessRequest(HttpContext context)
{
try
{
int width;
int height;
//Verifica se o usuario passou a largura da figura
if (context.Request.QueryString["width"] != null)
{
width = int.Parse(context.Request.QueryString["width"]);
}
else
{
width = 100;
}
//Verifica se o usuario passou a altura da figura
if (context.Request.QueryString["height"] != null)
{
height = int.Parse(context.Request.QueryString["height"]);
}
else
{
height = 100;
}
// Pega o caminho do arquivo fisico
string path = context.Request.PhysicalPath;
// Pega a extensão para determinar o tipo da imagem
string contentType = path.Substring(path.LastIndexOf(".") + 1);
ImageFormat newFormat;
// Altera o formato dependendo do tipo do arquivo
switch (contentType)
{
case "gif":
newFormat = ImageFormat.Gif;
break;
case "jpg":
newFormat = ImageFormat.Jpeg;
contentType = "jpeg";
break;
case "png":
newFormat = ImageFormat.Png;
break;
default:
newFormat = ImageFormat.Jpeg;
break;
}
// Arquivo Bitmap com o thumbnail ja criado
Bitmap newThumb = CreateThumbnail(path, width, height);
// Seta o ContentType ( image/jpeg, image/gif ... )
context.Response.ContentType = "image/" + contentType;
// Salva a imagem no Output que retornara ao usuario.
newThumb.Save(context.Response.OutputStream, newFormat);
newThumb.Dispose();
}
catch (Exception ex)
{
throw;
}
}
}
}
Então blz! criamos a classe! Mas para podermos habilitar esse handler precisamos adicionar uma tag a mais no web.config, dentro de <configuration><system.web> adicione essa tag:
Mas o que é essa configuração? uma breve explicação:
Type: Nome da Classe / DLL separado por virgula se for mais de um.
Verb: A lista de verbos que seu componente utiliza, separados por virgula e entre aspas ex: (“GET,POST,HEAD”)
Path: A URL inteira ou parte dela em que o seu Handler ira ser invocado. Ex: *.aspx ( o seu handler executara em todas paginas .aspx ) ou default.aspx (apenas nessa pagina )
Obs: Isso só funciona a partir do IIS 6.0. Antes disso tinha que adicionar o Handler direto no IIS.
Então é isso ai, agora é só criar uma pagina com uma imagem como eu fiz aqui, lembrando que a proporção é realizada automaticamente:

Você pode adicionar o método no onclick chamando a imagem com o tamanho maior.
Isso foi só uma demonstração do uso de httpHandlers, há vários outro jeitos de melhorar esse nosso Thumbnail, depende da criatividade/necessidade de cada um. Uma outra coisa bacana seria fazer marca d’água em suas imagens (só em imagens em alguma pasta especifica por exemplo ).
Bom Filhotes, qualquer duvida me avisem! Ate mais!
Fontes:
http://www.15seconds.com/issue/020417.htm
http://msdn.microsoft.com/pt-br/library/7d6sws33%28VS.85%29.aspx
Fala Filhotes! Hoje irei mostrar uma novidade do C# 4.0. Algo muito, muito bacana e igualmente simples... são os Parâmetros Opcionais e consequentemente os Parâmetros Nomeados. Uma das coisas que eu senti falta quando eu migrei do VB.Net para o C# foi a falta de Parâmetros opcionais. “ Mas André, o que é Parâmetro Opcional ? “ A idéia é muito simples, é um Parâmetro com um valor padrão que não precisa ser preenchido. Isso deixa o código mais simples e diminui o numero de overloads. Vamos aos exemplos:
Vamos dizer que temos uma função para gravar os logs dos erros que recebe o erro, o usuario e o caminho do arquivo de log como Parâmetros.
... {
GravaLog("Erro 123: nada nada nada","andre",c:\\log22_06.txt");
}
static bool GravaLog(string texto, string usuario,
string caminhoLog)
{
try
{
StreamWriter sw = new StreamWriter(caminhoLog);
sw.WriteLine("usuario: " + usuario + ":" + texto);
sw.Flush();
}
catch (Exception ex)
{
return false;
}
return true;
}
Normal até ai, mas e se quisermos fazer a função gravar em um arquivo de Log padrão quando nós não enviarmos o caminho de um arquivo especifico? Ou mesmo se não tivermos o usuario ainda? Antigamente teriamos de fazer um novo overload para cada um desses casos, mas graças nós podemos fazer isso de um jeito muito melhor:
Olha como fica:
static bool GravaLog(string texto, string usuario = "System",
string caminhoLog = "c:\\log.txt")
{
try
{
…
Viu como é simples? Atribuimos um valor default nos Parâmetros. Mas o que isso muda?
Se chamarmos a função desse jeito:
GravaLog("Erro 123: nada nada nada");
O valor do usuario será System e do caminhoLog será c:\log.txt que são os valores que nós definimos como padrão. Você pode chamar também passando só o nome do usuario, ou mesmo todos os Parâmetros:
GravaLog("Erro 123: nada nada nada", "Jose");
Os Parâmetros que você passou terão os valores enviados para a função( como antigamente ) e os que você não passou usarão o valor padrão. Bem simples, né?
Mas temos temos regras a seguir para poder usa-los: Os Parâmetros opcionais sempre devem ser declarados por ultimo na função, tanto que vocês podem ver que na nossa função os 2 ultimos são opcionais, poderiamos ate por todos os Parâmetros opcionais mas não só o primeiro. Bom, mas e se quisermos enviar só o texto e o caminhoLog sem passar o usuario?
Ai é só usar os Named Parameters ( Parâmetros nomeados ). Veja como é simples:
GravaLog("Erro 123: nada nada nada",caminhoLog:"i:\\logteste.ini");
É só passar o nome do Parâmetro que você quer preencher seguido de ":"(dois pontos)
com o valor que você quer. Simples né? Mas claro, só funciona com os Parâmetros opcionais (que você deu um valor padrão).
Bom filhotes, é isso ai, qualquer duvida, só avisar.
Opa! Como vocês estão meus caros? Meu nome é André Castro e sou o mais novo camarada do 100loop! Eu sou MCP e trabalho como Analista de Sistemas na Webaula. Bom, hoje eu vou falar sobre algo relativamente fácil, os meus amigos Métodos Anônimos. Métodos anônimos começaram no C# 2.0 e a idéia é bem interessante e simples, veja bem: Temos um botão, o btnTeste, e precisamos adicionar uma funcionalidade no evento Click dele dinamicamicamente, para isso normalmente criamos um método com a funcionalidade que queremos, e depois atribuimos ao objeto com um EventHandler associado ao método:
protected void btnTeste_Click(object sender, EventArgs e)
{
if (divHide.Visible)
{
divHide.Visible = false;
}
else
{
divHide.Visible = true;
}
}
btnTeste.Click += new EventHandler(btnTeste_Click);
Ate aí tudo bem, mas veja bem, esse método só vai ser usado uma vez, precisavamos mesmo ter criado mais um método no código? Na verdade não, podemos usar um método anônimo para facilitar as coisas, visualize:
btnTeste.Click += delegate(Object o, EventArgs a)
{
if (divHide.Visible)
{
divHide.Visible = false;
}
else
{
divHide.Visible = true;
}
};
Agora conseguimos criar e adicionar o delegate ao mesmo tempo, olha como ficou mais facil. Percebe –se tambêm que o delegate não tem identificação, por isso é chamado de método anônimo. Deixe eu dar mais um exemplo, dessa vez criamos uma variavel que herda da Interface IEnumerable ( Mesma da Collection ) e vamos popular-la com uma sequencia de 1 a 10. E usar um método anônimo para pegar apenas os números pares:
// O método Range da classe Enumerable cria uma sequencia de numero, nesse caso
// estamos criando uma sequencia que começa do número 1 ao 10
IEnumerable sequenciaNum = Enumerable.Range(1, 10);
// Agora usamos o metodo Where da Interface IEnumerable para selecionarmos
// apenas os numeros pares
sequenciaNum = sequenciaNum.Where(delegate(int numero)
{
// o caracter % é o MOD do c# (Ele pega o RESTO de uma divisão pelo numero informado,
// nesse caso, o 2)
if (numero % 2 == 0) return true;
return false;
});
// Imprime o resultado
foreach (int num in sequenciaNum)
{
Console.WriteLine(num);
}
Obs: O método IEnumerable.Where recebe como parametro uma Func, isso significa que é uma função que precisa receber um parametro do mesmo tipo da nossa variavel, ou seja: Inteiro e retornar um valor booleano. Bom, ja entendemos um pouco dos tais métodos Anônimos apresentados no C# 2.0, mas acontece que no C# 3.0 nós temos a presença de mais um camarada, que de certa forma facilitam a nossa vida, são as Expressões Lambda ( Lambda Expressions ). As Expressões Lambda nos da uma sintaxe mais simples e funcional para escrevermos Métodos Anônimos, além de diminuir (bastante) nossas linhas de código, vamos usar o mesmo exemplo anterior, agora com as Expressões Lambda.
// O método Range da classe Enumerable cria uma sequencia de numero,
// nesse caso estamos criando uma sequencia que começa do número 1 ao 10
IEnumerable sequenciaNum = Enumerable.Range(1, 10);
// Agora com Expressões Lambda, olha como diminui a quantidade de código.
sequenciaNum = sequenciaNum.Where(numero => numero % 2 == 0);
// Imprime o resultado
foreach (int num in sequenciaNum)
{
Console.WriteLine(num);
}
Simples né? Bom talvez fique simples depois de eu explicar, vamos la, a idéia basica é: PARAMETROS => EXPRESSÃO O operador => significa que é uma Expressões Lambda. Nós trocamos toda a declaração do delegate:
delegate(int numero)
{
Apenas pelo parametro (
numero) e pelo operador
=>. Trocamos tambem o
if (numero % 2 == 0) return true;
return false;
Apenas pela condição numero % 2 == 0 . Como vocês podem ver as Expressões Lambda facilitam ainda mais o que os Métodos Anônimos ja facilitavam. Bom filhotes, é isso. Qualquer dúvida estou a disposição, abraços!