Buscar

CSharp - Guia rápido

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 3, do total de 35 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 6, do total de 35 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes
Você viu 9, do total de 35 páginas

Faça como milhares de estudantes: teste grátis o Passei Direto

Esse e outros conteúdos desbloqueados

16 milhões de materiais de várias disciplinas

Impressão de materiais

Agora você pode testar o

Passei Direto grátis

Você também pode ser Premium ajudando estudantes

Prévia do material em texto

1 
 
C# - Guia rápido 
A linguagem de Programação C# ......................................................................................................................................... 2 
As características do C# ................................................................................................................................................... 2 
“Olá Mundo”: A estrutura básica de uma aplicação C# (C Sharp) ................................................................................... 2 
Palavras-chave e palavras reservadas da linguagem C# .............................................................................................. 3 
Variáveis, tipos de dados, conversão entre tipos de dados e operadores....................................................................... 4 
Variáveis e seus tipos ................................................................................................................................................... 4 
Definindo Constantes .................................................................................................................................................. 4 
Conversão de dados .................................................................................................................................................... 5 
Principais operadores ...................................................................................................................................................... 7 
Comandos condicionais ................................................................................................................................................... 8 
O condicional if ......................................................................................................................................................... 8 
O condicional switch ................................................................................................................................................ 9 
Laços de repetição (loop) .............................................................................................................................................. 9 
Tratamento de erros ...................................................................................................................................................... 12 
O try ........................................................................................................................................................................... 12 
O catch ....................................................................................................................................................................... 13 
O finally ...................................................................................................................................................................... 14 
O throw ...................................................................................................................................................................... 14 
Arrays e classes de coleções (listas) ............................................................................................................................... 15 
Trabalhando com Arrays............................................................................................................................................ 15 
Acessando elementos do array ................................................................................................................................. 16 
Redimensionando arrays ........................................................................................................................................... 16 
Arrays bidimensionais (matrizes) .............................................................................................................................. 16 
Classes de coleções (listas) ........................................................................................................................................ 16 
Passando arrays como parâmetro ............................................................................................................................. 17 
Formatando valores em C# ............................................................................................................................................ 17 
Formatador padrão ................................................................................................................................................... 17 
Formatador customizado .......................................................................................................................................... 18 
Criando um arquivo texto .............................................................................................................................................. 18 
Criando pastas no sistema de arquivos.......................................................................................................................... 19 
Movendo e Copiando arquivos ...................................................................................................................................... 19 
Definindo classe e criando objetos ..................................................................................................................................... 20 
Utilizando Construtores ................................................................................................................................................. 23 
Utilizando Destrutores ................................................................................................................................................... 24 
Propriedades .................................................................................................................................................................. 24 
Modificadores de acesso ............................................................................................................................................... 25 
Métodos e passagem de parâmetros ............................................................................................................................ 25 
Os modificadores in/out/ref .......................................................................................................................................... 27 
O modificador ref ...................................................................................................................................................... 28 
O modificador out...................................................................................................................................................... 28 
Herança .......................................................................................................................................................................... 29 
Polimorfismo .................................................................................................................................................................. 31 
Conversão entre as classes ............................................................................................................................................ 33 
Classes Abstratas............................................................................................................................................................ 33 
Interfaces ....................................................................................................................................................................... 34 
2 
 
A linguagem de Programação C# 
A Microsoft define o C# como a principal linguagem de programação para uso na plataforma .NET. Por 
ser uma derivação da linguagem C++, sem as suaslimitações, e é uma linguagem bastante simples de se 
programar. 
As características do C# 
Dentre as características essenciais do C# podemos citar: 
• Simplicidade: os projetistas de C# costumam dizer que essa linguagem é tão poderosa quanto o 
C++ e tão simples quanto o Visual Basic. 
• Completamente orientada a objetos: em C#, tudo é classe. System.Object é a classe base de 
todo o sistema de tipos de C#. 
• Fortemente tipada: isso ajuda a evitar erros por manipulação imprópria de tipos, atribuições 
incorretas etc. 
• Case sensitive: diferencia caracteres maiúsculos e minúsculos. 
• Controle de versões: cada assemblie gerado, seja como EXE ou DLL, tem informação sobre a 
versão do código, permitindo a coexistência de dois assemblies homônimos, mas de versões 
diferentes no mesmo ambiente. 
• Suporte a código legado: o C# pode interagir com código legado de objetos COM e DLLs escritas 
em uma linguagem não-gerenciada. 
• Flexibilidade: se o desenvolvedor precisar usar ponteiros, o C# permite, mas ao custo de 
desenvolver código não-gerenciado, chamado “unsafe”. 
• Linguagem gerenciada: os programas desenvolvidos em C# executam num ambiente gerenciado, o 
que significa que todo o gerenciamento de memória é feito pelo runtime via o GC (Garbage 
Collector), e não diretamente pelo programador, reduzindo as chances de cometer erros 
comuns em linguagens de programação onde o gerenciamento da memória é feito diretamente 
pelo programador. 
“Olá Mundo”: A estrutura básica de uma aplicação C# (C Sharp) 
O código a seguir implementa um programa em modo console (caractere) que é executado no prompt 
de comando. O resultado da execução é a saída “Olá Mundo”. Salve o código abaixo num arquivo texto e dê o 
nome de OlaMundo.cs. Observe que “OlaMundo” é o nome da classe e do arquivo, e “.cs” é a extensão do 
arquivo e também identifica qual linguagem o código foi implementado, neste caso o C# (CSharp). 
using System; //namespace 
 
public class OlaMundo //identificação da classe 
{ 
 public static void Main(string[] args) //identificação do método principal 
 { 
 //código 
 Console.WriteLine("Olá Mundo!"); 
 Console.ReadKey(); 
 } 
3 
 
} 
 
Todo programa em C# é uma classe. O programa acima é bem primário e possui 4 elementos básicos, 
uma declaração de namespace, declaração da classe, um método principal, e duas linhas de código. 
Para compila-ló é necessário usar o compilador C#, o CSC.exe. Ele é encontrado no diretório de 
instalação do .NET Framework e deve estar referenciado no path do Windows. Para referenciar o compilador 
digite PATH %path%;C:\Windows\Microsoft.NET\Framework\v3.5 no prompt de comando. Neste caso a versão 
do .NET Framework é a 3.5. 
O programa pode ser compilado através do prompt de comando por meio da instrução csc 
OlaMundo.cs, se nenhum erro ocorrer, será gerado um assemblie chamado OlaMundo.exe, é só executar. 
Todo programa C# deve ter uma classe que defina o método Main(), que deve ser declarado como 
estático usando o modificador static, isto diz ao runtime que o método pode ser chamado sem que a 
classe seja instanciada. É através desse modificador que o runtime sabe qual será o ponto de entrada do 
programa, para poder passar o controle ao runtime .NET. 
O “M” maiúsculo do método Main é obrigatório, e seu valor de retorno void significa que o método 
não retorna nenhum valor quando é chamado. 
Veja o código MSIL gerado pela compilação abrindo o assemblie gerado (OlaMundo.exe) com o 
programa IL Disassembler encontrado junto com o compilador da linguagem. 
Importante observar que strings em C# utilizam são delimitadas por aspas (“ ”) enquanto 
caracteres utilizam apóstrofos (‘ ’). 
Em C# é permito 2 tipos de comentários. No exemplo acima foram utilizados os dois tipos de 
comentários: // e /* ... */. 
Sintaxe Descrição 
// Comentário de linha: Comentário iniciado por //, restrito a uma única linha. 
/* ... */ Comentário de bloco: Comentário delimitado por /* e */, para blocos de código. 
 
Palavras-chave e palavras reservadas da linguagem C# 
abstract event new struct 
as explicit null switch 
base extern object this 
bool false operator throw 
break finally out true 
byte fixed override try 
case float params typeof 
catch for private uint 
char foreach protected ulong 
checked goto public unchecked 
class if readonly unsafe 
const implicit ref ushort 
continue in return using 
4 
 
decimal int sbyte virtual 
default interface sealed volatile 
delegate internal short void 
do is sizeof while 
double lock stackalloc 
else long static 
enum namespace string 
 
Variáveis, tipos de dados, conversão entre tipos de dados e operadores 
Esta sessão introduz os operadores, variáveis e seus tipos em C# como também a conversão entre os 
tipos de dados. 
Variáveis e seus tipos 
A declaração de variáveis no C# não possui um comando específico como em outras linguagens de 
programação (Dim no Visual Basic e var no Javascript). A declaração de variáveis em C# é feita 
informando-se o tipo de dado a ser utilizado e em seguida o nome da variável, conforme o exemplo a seguir. 
 string nome; 
 int idade; 
 
 //Declarando e inicializando a variável na mesma instrução 
 string sexo = “M”; 
Tipos de dados 
Tipo .NET Framework Sintaxe C# Faixa de Dados Significado Classificação 
System.Boolean bool True ou false (verdadeiro ou falso) Representa valores true e false Value-types 
System.Byte byte 0 a 255 (8 bits) Inteiro de 8-bit sem sinal Value-types 
System.SByte sbyte -128 a 127 (8 bits) Value-types 
System.Char char 0 a 65535 (16 bits) Um caractere Value-types 
System.Decimal decimal ±1.0 × 10-28 a ±7.9 × 1028 (128 bits) Tipo numérico para cálculos 
financeiros (28 casas decimais) 
Value-types 
System.Double double ±5.0 × 10-324 a ±1.7 × 10308 (64 
bits) 
Ponto flutuante de precisão dupla 
(15 casas decimais) 
Value-types 
System.Single float ±1.5 × 10-45 a ±3.4 × 1038 (32 bits) Ponto Flutuante de precisão 
simples (7 casas decimais) 
Value-types 
System.Int32 int -2.147.483.648 a 2.147.483.647 (32 
bits) 
Inteiro 
Value-types 
System.UInt32 uint 0 a 4.294.967.295 (32 bits) inteiro sem sinal Value-types 
System.Int64 long –9.223.372.036.854.775.808 a 
9.223.372.036.854.775.807 (64 bits) 
Inteiro Longo 
Value-types 
System.UInt64 ulong 0 a 18.446.744.073.709.551.615 (64 
bits) 
inteiro longo sem sinal 
Value-types 
System.Int16 short -32.768 a 32.767 (16 bits) Inteiro Short Value-types 
System.UInt16 ushort 0 a 65.535 (16 bits) Um inteiro short sem sinal Value-types 
System.String string Seqüência de caracteres (16 bits por 
caractere) 
Uma sequência de caracteres 
Reference-Type 
Definindo Constantes 
Outra estrutura importante que pode ser construída no C# são as constantes. As constantes são 
valores que não alteram seu valor durante a execução do programa. Em geral são utilizados para parâmetros 
de configuração ou para valores fixos representados por um nome para maior clareza. 
5 
 
As constantes são declaradas através da palavra const, e assim como qualquer outra estrutura de 
programação deve ser declarada dentro de uma classe. O exemplo a seguir mostrar como declarar uma 
constante. 
 
 cont int segundos = 60; 
 
 
Conversão de dados 
Quando precisamos atribuir o valor de uma variável para outra variável de um tipo diferente o C# 
exige a utilização de uma função de conversão. Diferente de outras linguagens, como o Visual Basic, o C# exige 
a conversão explicita de dados na maioria dos casos. Vamos analisar os diferentes tipos de conversões 
possíveis no C#. 
Conversão Explicita 
A conversão explicita pode ser feita atravésda utilização de operadores de “cast” (conversão). Um 
operador de cast é utilizado informando-se o tipo de dados entre parênteses antes da atribuição do valor à 
variável de um tipo diferente. Um exemplo de operação de cast explicito pode ser observada a seguir. 
 int valorInteiro; 
 double valorGrande = 10; 
 
 //convertendo 
 valorInteiro = (int)valorGrande; 
 
No exemplo acima para converter um valor do tipo double para o tipo int, é necessário 
informarmos um operador de conversão antes da atribuição (int). Se não informarmos a função de 
conversão, conforme o exemplo acima recebemos um erro de compilação. 
Conversão Implicita 
Apesar da exigência de uma função de conversão na maioria dos casos, conforme vimos no exemplo 
acima, existem alguns casos em que a função de conversão não se faz necessária. Quando fazemos a 
conversão de um tipo de dados de menor magnitude para um de maior magnitude, a função de conversão não 
é necessário, tendo em vista que não corremos o risco de ter perda de valores no processo de conversão, 
conforme o exemplo a seguir. 
 int valorInteiro = 10; 
 double valorGrande; 
 
 //convertendo 
 valorGrande = valorInteiro; 
 
Conversões para strings 
A conversão de strings funciona de uma maneira um pouco diferente do que as conversões 
apresentadas nos exemplos acima. As strings só podem ser convertidas através de funções especiais, 
capazes de realizar este tipo de conversão. 
6 
 
A conversão de uma variável qualquer para string é um processo mais simples dentro de uma 
aplicação .NET. Para convertermos um valor para o tipo string, basta informarmos a chamada do método 
ToString() após o nome da variável que possui o valor a ser convertido. Todo e qualquer tipo de dados do 
.NET possui a função ToString e em alguns casos esta função pode inclusive receber parâmetros. Um 
exemplo de conversão para o tipo string pode ser observado a seguir. 
 string mensagem; 
 
 int valor1, valor2; 
 valor1 = 10; 
 valor2 = 15; 
 
 int result = valor1 + valor2; 
 
 mensagem = "O resultado da soma de 10 + 15 é " + result.ToString(); 
 
No exemplo acima estamos somando duas variáveis do tipo inteiro e concatenando o valor convertido 
para string em uma variável chamada mensagem. 
Convertendo string para outros valores 
A conversão de strings para outros valores se dá através do uso de uma classe especial para 
conversão, a classe Convert. A classe Convert é capaz de converter uma string para qualquer tipo 
primitivo de dados. A função a ser utilizada deve ser To<Tipo de Dado>. Abaixo temos um exemplo de 
uso da classe Convert. 
 string numero = "1000"; 
 
 int valor = Convert.ToInt32(numero); 
 short valor2 = Convert.ToInt16(numero); 
 
 DateTime dt = Convert.ToDateTime("01/01/2007"); 
 
Outra opção para conversão de strings é a utilização da função Parse de um tipo específico. A 
maioria dos tipos de dados suporta a função Parse, que permite a conversão de string para um valor, 
conforme exemplo a seguir. 
 string numero = "1000"; 
 
 int valor = Int32.Parse(numero); 
 short valor2 = Int16.Parse(numero); 
 
 DateTime dt = DateTime.Parse("01/01/2007"); 
 
 
 
 
7 
 
Validando a conversão de tipos 
Muitas vezes precisamos testar o dado contido em uma variável antes de realizamos sua conversão 
para outro tipo de dado. Isso pode ser feito facilmente através de tratamentos exceções, mas não é uma boa 
prática de programação, pois consome recursos desnecessários para uma conversão de tipo de dados. 
Algumas classes de definição de tipos oferecem o método TryParse() que retorna um valor 
boleano que representa se a conversão ocorreu com sucesso ou não, e retorna o valor convertido no segundo 
parâmetro do método como out. Mesmo que o retorno seja falso, ou seja não foi possível realizar ele vai 
retornar o segundo parâmetro inicializado com 0 (zero). Vejamos um exemplo. 
 string entradaDados; 
 int resultado; 
 
 Console.Write("Digite algo: "); 
 entradaDados = Console.ReadLine(); 
 
 if (int.TryParse(entradaDados, out resultado)) 
 { 
 Console.WriteLine("É inteiro."); 
 } 
 else 
 { 
 Console.WriteLine("NÃO É inteiro."); 
 } 
 
 Console.WriteLine("Resultado da conversão: {0} ", resultado); 
 Console.ReadKey(); 
 
Principais operadores 
Em C#, os operadores podem ser classificados da seguinte forma: aritméticos, unários, lógicos, 
condicionais, relacionais, igualdade e de atribuição. 
 
Operadores Aritméticos 
Operador Uso 
+ Soma tipos numéricos. Também é usado para concatenar strings. 
- Efetua a diferença de tipos numéricos. 
/ Efetua a divisão de tipos numéricos. 
* Efetua o produto de tipos numéricos. 
% Retorna o resto da divisão. 
Operadores Condicionais 
Operador Uso 
&& Operador lógico AND usado para comparar expressões booleanas. 
|| Operador lógico OR usado para comparar expressões booleanas. 
?: 
Operador ternário usado da seguinte forma: 
expr. a: expr. b? expr. c. 
Isso equivale a dizer: 
if (expr. a) 
 expr. b; 
else 
 expr. c; 
Operadores Relacionais 
Operador Uso 
< Condição “menor que” para tipos numéricos. 
> Condição “maior que” para tipos numéricos. 
>= Condição “maior ou igual que” para tipos numéricos. 
8 
 
<= Condição “menor ou igual que” para tipos numéricos. 
is Compara em tempo de execução se um objeto é compatível como um tipo qualquer. 
Esse assunto será abordado mais adiante. 
as 
Efetua mascaramento de tipos e caso este falhe, o resultado da operação será null. Esse 
assunto será abordado mais adiante. 
Operadores de Igualdade 
Operador Uso 
== Avalia a igualdade de dois tipos. 
!= Avalia a desigualdade de dois tipos. 
Operadores de Atribuição 
Operador Uso 
= 
Atribuição simples. No caso de atribuição entre objetos, referências são atribuídas e não 
valores. 
*= Multiplicação seguida de atribuição. Exemplo: x*= 10 que é equivalente a x = x*10. 
/= Divisão seguida de atribuição. Exemplo: x/= 10 que é equivalente a x = x/10. 
%= Resíduo seguido de atribuição. Exemplo: x%= 10 que é equivalente a x = x % 10. 
+= Soma seguida de atribuição. Exemplo: x += 10 que é equivalente a x = x + 10. 
-= Subtração seguida de atribuição. Exemplo: x -= 10 que é equivalente a x = x – 10. 
<<= 
Deslocamento de X à esquerda pelo número de bits indicado pela segunda variável/valor 
seguido de atribuição. Exemplo: x<<=5 que é equivalente a x = x << 5. 
>>= 
Deslocamento de X à direita pelo número de bits indicado pela segunda variável/valor, 
seguido de atribuição. Exemplo: x>>5 que é equivalente a x = x >>5. 
&= Operação AND seguida de atribuição. Exemplo: x &= 0x0a que é equivalente a x = x & 
0x0a. 
^= 
Operação XOR seguida de atribuição. Exemplo: x ^= 0x0a que é equivalente a x = x ^ 
0x0a. 
|= Operação OR seguida de atribuição. Exemplo: x |= 0x0a que é equivalente a x = x | 0x0a. 
Tabela 1: Operadores suportados pela linguagem C#. 
Comandos condicionais 
Em C# existem dois tipos de condicionais: if e switch. 
O condicional if 
O if avalia uma expressão lógica booleana e qualquer outro tipo será acusado como erro pelo 
compilador. Se o resultado for verdadeiro, o bloco de código dentro do if será executado, caso contrário, o 
controle é passado para a próxima declaração depois do if. Os projetistas de C# optaram por aceitar 
unicamente expressões booleanas no if para evitar escrever código com semântica obscura e propensa a 
resultados inesperados. 
A declaração if tem três formas básicas: 
1. 2. 3. 
 
if (expressão) 
{ 
 Declaração 
} 
 
if (expressão){ 
 Declaração 
} 
else 
{ 
 Declaração 
} 
 
if (expressão) 
{ 
 Declaração 
} 
else if (expressão) 
{ 
Declaração 
} 
else (expressão) 
{ 
 Declaração 
} 
9 
 
O condicional switch 
A declaração switch avalia uma expressão cujo resultado pode ser dos tipos sbyte, byte, short, 
ushort, int, uint, long, ulong, char, string ou enum, e este por sua vez é comparado com cada 
uma das seções case que constituem o switch. Vejamos a sua sintaxe: 
switch(expressão) 
{ 
 case constante1: 
 declaração 1; 
 break; 
 case constante2: 
 declaração 2; 
 break; 57 
 ... 
 [default: 
 declarações; 
 break; 
 ] 
} 
 
Em C#, é obrigatório que cada seção case tenha uma declaração break. A seção default, é 
avaliada caso nenhuma das seções case forem verdadeira, equivale ao else do if. Seu uso não é 
obrigatório. E não pode existir mais de uma seção case com a mesma constante. 
Laços de repetição (loop) 
A linguagem C# dá suporte a quatro tipos diferentes de laços: for, foreach/in, while, e 
do/while. 
O laço for 
O laço for trabalha checando uma condição para executar um bloco de código até que essa condição 
seja verdadeira, no caso do laço for temos que em sua sintaxe declarar sua inicialização, sua condição e seu 
incremento, veja: 
for (int i = 0; i <= 10; i++) 
{ 
 //instruções 
} 
 
No código acima temos a sintaxe um laço for onde na primeira parte declaramos uma variável do 
tipo inteiro (int) e a inicializamos com o valor 0 (zero), na segunda parte temos a condição nesse caso verifica 
se a nossa variável recém criada é menor ou igual a 10 e a terceira e última parte é o incremento desta 
variável, sendo essas três partes separadas por ';' (ponto e virgula). O funcionamento é simples, todo código 
dentro do bloco for será executado dez vezes. 
Para abandonar o laço antes que a condição for seja falsa, usa-se a palavra reservada break. 
for (int i = 0; i <= 10; i++) 
{ 
 Console.WriteLine("Iteração número {0}", i); 
 if (i == 3) 
 break; 
} 
 
10 
 
A palavra reservada continue permite que o fluxo de execução da iteração corrente seja 
abandonado, mas não o laço, e que a iteração seguinte dê início no topo do laço, uma vez que a condição do 
for seja satisfeita. 
for(int i=0; i<=10; i++) 
{ 
 Console.WriteLine("Iteração número {0}", i); 
 if (i == 3) 
 break; 
} 
 
for(int i=0; i<=10; i++) 
{ 
 Console.WriteLine("Iteração número {0}", i); 
 if (i == 3) 
 continue; 
 // a declaração a seguir não será executada quando i==3 
 Console.WriteLine ("Iteração número {0}", i +2 ); 
} 
 
O laço foreach/in 
O laço foreach é usado para percorrer listas. Ele opera sobre Arrays ou coleções veja sua sintaxe 
básica: 
foreach(<tipo de dado> <nome> in <lista>) 
{ 
 //instruções 
} 
 
Vejamos um exemplo pratico para facilitar o entendimento: 
string[] nomes = { "Maria", "João", "Sebastião", "Josefa" }; 
 
foreach (string pessoa in nomes) 
{ 
 Console.WriteLine("{0} ", pessoa); 
} 
 
Criamos um array de string e colocamos alguns elementos dentro e no nosso laço foreach, 
como resultado será exibido todos os elementos dentro de nosso array. 
As suas vantagens em relação ao laço for são as seguintes: 
• Não precisamos nos preocupar com a avaliação da uma condição booleana para garantir a sua 
execução; 
• Nem com a inicialização de variáveis com o seu incremento/decremento; 
• Nem com a forma de extração do conteúdo do array ou coleção, já que ambos possuem 
formas diferentes de extração dos seus valores; 
• Quando todos os elementos do array/coleção tiverem sido varridos, o laço foreach/in 
será abandonado; 
11 
 
• O uso do comando break é valido para quebrar a execução. 
O laço while 
De modo diferente do laço for (embora o objetivo seja o mesmo, ou seja, repetir a execução de um 
código testando uma condição) o laço while é mais simples de ser entendido, pois sua sintaxe não requer 
que você coloque na mesma linha a variável de inicialização, a condição e o seu incremento. No laço while 
apenas colocamos a condição que queremos testar, veja como fica: 
while (expressão booleana) 
{ 
 //instruções 
} 
 
Veja como é simples o código. Expressão booleana é uma expressão que sempre retorna falso ou 
verdadeiro e a instruções dentro do bloco de código do laço while só será executada enquanto essa 
expressão retornar verdadeiro. Veja um exemplo: 
int contador = 2; 
 
while (contador != 10) 
{ 
 Console.WriteLine(contador.ToString()); 
 contador++; 
} 
 
Neste caso temos uma variável chamada contador e seu valor é 2, e no laço while testamos se a 
variável contador é diferente de 10, caso verdadeiro mostramos na tela o valor atual da variável contador e o 
incrementos em 1 e o laço while continuará até que essa condição se torne falsa. 
Temos de ter cuidado para não causar um loop infinito, ou seja, a condição nunca será falsa e o laço 
vai continuar até travar a máquina. 
As palavras reservadas break e continue também podem ser usadas no laço while da mesma 
forma do laço for. 
O laço do...while 
Se fossemos analisar com cuidado laço while, veríamos que dependendo do caso pode nunca ser 
executado, ou seja, se a condição do laço while retorna falsa de primeira ele nunca vai ser executado. No 
exemplo anterior se atribuíssemos o valor 10 a variável “contador” em sua declaração, o laço while nunca 
começaria. Com o do.. while o código será executado ao menos uma vez porque verificação da condição é 
no final da instrução, veja: 
do 
{ 
//instruções 
} 
while (expressão booleana) 
 
12 
 
Podemos traduzir “do” para “faça”, ou seja, faça as instruções enquanto (while) expressão seja 
verdadeira. Assim garantimos que ao menos uma vez as instruções serão executadas. Exemplo: 
int contador = 10; 
 
do 
{ 
 Console.WriteLine(contador.ToString()); 
} 
while (contador != 10); 
 
Veja que mesmo “contador” sendo igual a 10 a instrução será executa ao menos uma vez porque só 
depois que fazemos a verificação. 
As palavras reservadas break e continue também podem ser usadas no laço do...while da 
mesma forma do laço for. 
Tratamento de erros 
Qualquer um que já foi um simples usuário de software já se deparou com uma mensagem de erro na 
sua frente, alguns softwares têm mensagens que só ajudam o desenvolvedor, alguns só o usuário e outros tem 
mensagens que não ajudão em nada. O tratamento de erros consiste em interceptar/capturar esses erros a 
fim de que o programa não aborte inesperadamente e informe ao usuário o que está errado. 
Na plataforma .NET esses erros são chamados exceções (ou exceptions) e são tratados com as 
instruções try, catch e finally. O C# adota um estilo relativamente comum em outras linguagens, que é 
o de tratar erros como objetos que encapsulam todas as informações que necessitamos para resolvê-lo. Essa 
ideia é válida para todo ambiente .NET e foi batizada como SEH (Structured Exception Handling). 
A ideia básica é mais ou menos a seguinte: todo objeto que representa uma exceção é derivado de 
System.Exception. Essa classe possui os seguintes membros: 
Propriedade Significado 
HelpLink Retorna uma URL para um arquivo de Help descrevendo o erro em detalhes. 
Message Esta propriedade é somente leitura e descreve o erro. 
Source Retorna o nome do objeto ou aplicação que gerou o erro. 
StackTrace 
Esta propriedade é somente leitura e contém uma string que identifica a seqüência de 
chamadas que disparou o erro. 
InnerException Pode ser usada para preservar os detalhes do erro ao longo de uma série de exceções. 
 
Para tratar as exceções definimos um bloco do código que o runtime irá "tentar" (try) executar,se 
algo der errado ele vai executar o que estiver num bloco especifico (catch) que contem o que fazer numa 
situação dessas. Nesse bloco normalmente disparamos alguma mensagem. Também é possível criar um bloco 
que será sempre executado dando erro ou não (finally). 
O try 
O try é o bloco de código para escopo normal. As linhas de código que você simplesmente colocaria 
dentro do método, passam a ficar dentro do bloco de try onde será executado uma tentativa normal. 
 //Sem o uso do bloco try… 
 public void TesteMetodo1(string teste) 
13 
 
 { 
 Console.Write((Convert.ToInt32(teste))+1); 
 } 
 
 //Com o uso do bloco try… 
 public void TesteMetodo2(string teste) 
 { 
 try 
 { 
 Console.Write((Convert.ToInt32(teste))+1); 
 } 
 catch{} 
 } 
 
No exemplo acima estamos convertendo um tipo string para inteiro. Isso só é possível se o valor 
contido na variável “teste” seja um número inteiro. Assim runtime converte o valor de string para inteiro. 
Caso contrário será gerada uma exceção e o escopo do programa é direcionado para o bloco catch ao qual 
iremos falar mais abaixo. 
O catch 
O catch é o bloco que trata o erro gerado. Dentro deste bloco pode ser vista a mensagem do erro e 
feita a devida manipulação que o desenvolvedor quiser, como fechar o programa, retornar algo que 
identifique o erro ou simplesmente mostrar a mensagem de erro que foi gerada. 
 //Com o uso do bloco catch… 
 public void TesteMetodo(string teste) 
 { 
 try 
 { 
 Console.Write((Convert.ToInt32(teste))+1); 
 } 
 catch ( FormatException e) 
 { 
 Console.Write(e.Message.ToString()); 
 } 
 } 
 
No bloco catch anteriormente mostrado, apenas será exiba a mensagem de erro a qual a exceção 
gerada mostra. O bloco catch pode ser repetido várias vezes para serem tratados vários tipos de exceção. 
 public void TesteMetodo(string teste) 
 { 
 try 
 { 
 Console.Write((Convert.ToInt32(teste))+1); 
 } 
 catch (FormatException e) 
 { 
 Console.Write(e.Message.ToString()); 
 } 
 catch (InvalidCastException e) 
 { 
 Console.Write(e.Message.ToString()); 
 } 
 } 
 
 Existe ainda um tipo de exceção padrão para todos os erros. Este tipo de exceção é chamado apenas de 
Exception e é usada da seguinte forma. 
14 
 
 public void TesteMetodo(string teste) 
 { 
 try 
 { 
 Console.Write((Convert.ToInt32(teste))+1); 
 } 
 catch (Exception e) 
 { 
 Console.Write(e.Message.ToString()); 
 } 
 } 
O finally 
O finally é como nome já diz o bloco de finalização. Este bloco é executado em qualquer 
circunstância. Mesmo que o programa gere uma exceção o bloco finally será executado. A ideia é que 
existe um escopo rodando mesmo que o erro faça o programa parar, assim é possível fazer com que você 
possa matar conexões ou coisas do tipo, para que essas coisas não consumam carga de processamento e 
memória. 
 public void testeMetodo(string teste) 
 { 
 string Resp = ""; 
 try 
 { 
 Console.Write((Convert.ToInt32(teste))+1); 
 Resp = "Funcionou"; 
 } 
 catch (Exception e) 
 { 
 Console.Write(e.Message.ToString()); 
 Resp = "Erro"; 
 } 
 finally 
 { 
 Console.Write(Resp); 
 } 
 } 
 
No código mostrado acima, se o escopo normal for realizado dentro do bloco try, quando ele for 
executar o finally irá mostrar a mensagem “Funcionou”. Caso contrário, quando for executado o catch 
irá mudar o valor para “Erro” e assim quando for executado finally irá ser mostrada esta mensagem na 
tela. 
O throw 
O throw é um complemento aos blocos de código. Ele tem como função explodir uma exceção que 
pode ou não ser criada pelo usuário. 
 public static void TesteMetodo(string teste) 
 { 
 string Resp = ""; 
 int saida; 
 try 
 { 
 if (teste == null) 
 { 
 throw new ArgumentNullException(); 
 } 
 
 if (!Int32.TryParse(teste, out saida)) 
 { 
 throw new Exception("Valor inválido."); 
 } 
 
15 
 
 Console.Write(saida + 1); 
 Resp = "Funcionou"; 
 } 
 catch (ArgumentNullException e) 
 { 
 Console.Write(e.Message.ToString()); 
 Resp = "Informe um parâmetro."; 
 } 
 catch (Exception e) 
 { 
 Console.Write(e.Message.ToString()); 
 } 
 
 finally 
 { 
 Console.Write(Resp); 
 } 
 } 
 
No exemplo mostrado é checado se a variável teste é nula. Caso a mesma esteja nula é estourada uma 
exceção de valor NULL, fazendo com que o escopo do programa seja direcionado para o bloco catch. É 
também testado se o valor é um inteiro, se não é estourada outra exceção. 
Arrays e classes de coleções (listas) 
De forma simples um array é um conjunto de elementos de um mesmo tipo de dado onde cada 
elemento desse conjunto é acessado através de um índice. Um array é também conhecido como vetor 
(quando unidimensional) ou matriz (quando bidimensional). 
Trabalhando com Arrays 
Além das variáveis normais, o C# ainda possui suporte a criação de arrays. Os arrays são 
declarados de forma semelhante às variáveis convencionas, mas possuem um modificador [ ] que indica que a 
variável é um array, conforme exemplo. 
// Apenas um inteiro 
int valor; 
 
// Um array de inteiros 
int[] valores; 
 
Quando declaramos um array no C#, este array encontra-se em um estado não inicializado. Para 
inicializar um array devemos utilizar o comando new indicando o tamanho a ser alocado para o array. O 
tamanho do array é informado dentro dos colchetes, conforme exemplo a seguir. 
// Array com 5 inteiros 
int[] valores = new int[5]; 
 
//Array com 10 nomes, de 0 à 9 
string[] nomes = new string[10]; 
 
É possível ainda inicializar o array no seu dimensionamento, bastando para isto informar os itens do 
array logo após o comando new entre chaves, conforme o exemplo a seguir. 
16 
 
// Array com 5 inteiros 
int[] valores = new int[5] { 1, 2, 3, 4, 5 }; 
 
// Sem informar a dimensão 
string[] nomes = new string[] { "Nome1", "Nome2", "Nome3" }; 
Acessando elementos do array 
Para acessarmos elementos dos arrays, devemos informar entre colchetes o índice do array a ser 
acessado. Os arrays sempre iniciam pelo índice 0, conforme o exemplo a seguir. 
nomes[0] = "Nome1"; 
nomes[1] = "Nome2"; 
 
string var = nomes[3]; 
Redimensionando arrays 
Para redimensionarmos um array no C# devemos utilizar uma função da namespace 
System.Array, a função Resize. Esta função possibilita o redimensionamento do array. 
string[] nomes = new string[2]; 
 
nomes[0] = "Nome1"; 
nomes[1] = "Nome2"; 
System.Array.Resize(ref nomes,3); 
nomes[2] = "Nome3"; 
 
Arrays bidimensionais (matrizes) 
Vamos declarar um array de duas dimensões utilizando o modificar [,], veja: 
int[,] matriz = new int[2, 2]; 
 
Na sintaxe acima declaramos um array bidimensional com duas linhas e duas colunas, ou seja, temos 
um array com 4 posições: 
matriz [0, 0] = 1; 
matriz [0, 1] = 2; 
matriz [1, 0] = 3; 
matriz [1, 1] = 4; 
 
A ordem de acesso é sempre coluna x linha. 
Classes de coleções (listas) 
Apesar de suportar array, as operações com este tipo de estrutura em geral são complexas de se 
implementar. O mais comum é utilizarmos as classes de coleção. Estas classes abstraem a complexidade dos 
array, tornando o redimensionamento e a obtenção de itens automática. As classes de coleção fazem parte 
do namespace System.Collections. A seguir temos um exemplo da utilização da classe ArrayList. 
17 
 
System.Collections.ArrayList lista = new System.Collections.ArrayList(); 
 
lista.Add("Nome1"); 
lista.Add("Nome2"); 
lista.Add("Nome3"); 
lista.Remove("Nome2"); 
lista.RemoveAt(0); 
 
É possível observar que utilizando o ArrayList não há necessidade de redimensionamento quando 
inserimos ou removemos um item. 
Analogamente a classe ArrayList, a classe List do namespace 
System.Collections.Generic permite a criação de uma coleção para armazenamento de um 
conjunto de dados quaisquer. A diferença entre as duas bibliotecas é que a biblioteca genérica nos permite 
informar o tipo de dados o que queremos armazenar na coleção. Esta informação é indicada na declaração da 
coleção pelo parâmetro T, onde devemos informar o tipo de dados a ser utilizado. 
O exemplo a seguir cria uma lista de números inteiros e outra lista de uma classe definida pelo usuário. 
//Lista de valors inteiros 
List<int> listaInteiros = new List<int>(); 
listaInteiros.Add(10); 
int valor = listaInteiros[0]; 
//Lista de instância de uma classe definida pelo usuário 
List<MinhaClasse> listaMinhaClasse = new List<MinhaClasse>(); 
listaMinhaClasse.Add(new MinhaClasse()); 
Passando arrays como parâmetro 
Ao se passar um array como parâmetro por valor (in), os seus elementos se comportam como se 
fossem passados por referência. Isso significa que se alterarmos o valor de um elemento do vetor dentro do 
método, essa alteração vai ocorrer também no elemento do vetor passado como parâmetro. 
Formatando valores em C# 
Existem situações em que necessitamos formatar valores do tipo Data, Dinheiro, Inteiros ou Decimais. 
No C# temos dois grupos de formatadores, formatador padrão é formatador customizado. 
Formatador padrão 
A sintaxe é a seguinte: [Formato][Qtde. Casas Decimais]. O caracter que vem após os dois pontos é o 
formato em que o valor será exibido. Você também poderá optar por definir a quantidade de casas decimais 
da seguinte forma: C2. A seguir uma lista com os valores possíveis: 
Formatador 
Padrão 
Descrição 
C Exibe o valor no formato de moeda. 
D Exibe o valor no formato decimal. 
E Exibe o valor no formato científico (exponencial). 
F Exibe o valor no formato fixo. 
G Exibe o valor no formato geral. 
N Exibe o valor no formato numérico. 
P Exibe o valor no formato de porcentagem. 
X Exibe o valor no formato hexadecimal. 
18 
 
 
Os caracteres acima que especificam o formato a ser exibido, não são case-sensitive, exceto 
para o X, pois se ele for minúsculo os valores serão apresentados em minúsculo, do contrário, serão exibidos 
em maiúsculo. 
Formatador customizado 
Usado para formatar data e hora. 
Formatador Customizado Descrição 
MM/dd/yyyy Formato Mês/Dia/Ano. 
dd/MM/yyyy Formato Dia/Mês/Ano. 
HH:mm Formato Hora:Minuto. 
HH:mm:ss Formato Hora:Minuto:Segundo. 
dd/MM/yyyy hh:mm:ss Formato Dia/Mês/Ano Hora:Minuto:Segundo. 
 
Devemos nos atentar para o MM e para o mm, pois o maiúsculo significa Mês, já o minúsculo significa 
Minutos. Pode-se também ao invés de barras "/" utilizar o hífen "-" como separador para as Datas, ficando a 
string de formatação da seguinte forma: {0:dd-MM-yyyy hh:mm:ss}. Também existe diferença para o 
formatador que representa a hora. HH representa o formato 24 horas enquanto, hh representa o formato 12 
horas. 
 
Criando um arquivo texto 
Para manipulação de arquivos devemos importar o namespace System.IO, vamos agora criar um 
arquivo texto onde escreveremos algumas informações como exemplo. 
Existem várias maneiras de se abrir um arquivo texto no C#. Uma maneira muito simples é utilizando 
as classes StreamReader e StreamWriter. Estas classes permitem a gravação e a leitura de arquivos de uma 
maneira simples, fornecendo ainda métodos para a gravação e leitura de Strings nestes arquivos. Para 
utilizarmos estas classes, basta criarmos uma instancia das mesmas informando em seu construtor o nome do 
arquivo a ser aberto. 
Através dos métodos WriteLine e ReadLine, podemos gravar e ler informações dos arquivos texto de 
uma maneira bem simples. No exemplo abaixo, iremos abrir um arquivo texto para gravação e gravar algumas 
informações dentro dele. 
 StreamWriter file = new StreamWriter(@"C:\teste.txt"); 
 
 file.WriteLine("TESTE Linha 1"); 
 file.WriteLine("TESTE Linha 2"); 
 file.WriteLine("TESTE Linha 3"); 
 file.WriteLine("TESTE Linha 4"); 
 file.Close(); 
 
Se executarmos o exemplo de gravação de arquivos apresentado acima mais de uma vez, veremos que 
o arquivo é sobrescrito a cada execução. Para criarmos um StreamWriter capaz de realizar uma operação de 
inserção ao final de um arquivo (Append) basta informarmos um parâmetro adicional no construtor do 
19 
 
mesmo. No exemplo abaixo, estamos passando o valor de True para o parâmetro de append, permitindo que 
as informações sejam adicionadas no arquivo. 
 
 StreamWriter file = new StreamWriter(@"C:\teste.txt", true); 
 
 file.WriteLine("TESTE Linha 1"); 
 file.WriteLine("TESTE Linha 2"); 
 file.WriteLine("TESTE Linha 3"); 
 file.WriteLine("TESTE Linha 4"); 
 file.Close(); 
Note que ao finalizarmos a gravação das informações no arquivo, utilizamos o método Close para 
fechar o Stream. É importante fecharmos o arquivo sempre que terminamos de realizar qualquer operação 
com arquivos, do contrário o arquivo ficará aberto. 
No exemplo abaixo, iremos criar uma instancia da classe StreamReader para ler o arquivo que 
acabamos de criar. Utilizaremos o método ReadLine para ler as informações do arquivo. 
 StreamReader fileRead = new StreamReader(@"C:\teste.txt"); 
 
 string linha; 
 while (fileRead.Peek() > -1) 
 { 
 linha = fileRead.ReadLine(); 
 Console.WriteLine(linha); 
 } 
 fileRead.Close(); 
 
Notem que utilizamos o método Peek da classe StreamReader. Este método nos informa o número de 
caracteres restantes existentes no arquivo. Caso não existam mais caracteres a serem lidos, o método Peek 
retorna o valor de -1. 
Criando pastas no sistema de arquivos 
Agora que já vimos como criar e ler arquivos, vamos criar uma nova pasta para colocar este arquivo 
que acabamos de criar com nosso programa de exemplo. No namespace System.IO existe uma classe chamada 
Directory. Esta classe possui métodos para trabalharmos com pastas do sistema operacional. Para criarmos 
uma novo pasta basta chamarmos o método CreateDirectory, conforme o exemplo abaixo. 
 
 Directory.CreateDirectory(@"C:\NovoDir"); 
 
Movendo e Copiando arquivos 
A tarefa de mover arquivos e copiar arquivos também é simples. Para isto, basta utilizar os métodos 
compartilhados da classe File. O método MoveFile é utilizado para mover arquivos, enquanto o método 
CopyFile é utilizado para mover arquivos. 
No exemplo abaixo podemos ver um exemploda utilização dos dois comandos. 
 File.Copy(@"C:\teste.txt", @"C:\SubDir\Teste2.txt"); 
 File.Move(@"C:\teste.txt", @"C:\SubDir\Teste.txt"); 
 
20 
 
Definindo classe e criando objetos 
Numa aplicação desenvolvida com uma linguagem orientada a objetos o trabalho “pesado” é feito por 
classes. Mesmo aplicações pequenas em C# necessitam da elaboração de uma ou mais classes, cada uma com 
suas propriedades e métodos usados para executar as tarefas relativas ao objeto. 
Em C#, podemos ter dentro de uma classe os seguintes membros: atributos, construtores, destrutores, 
domínios, métodos, propriedades, indexadores, delegates, eventos e nested classes. 
A criação de classe usa basicamente a sintaxe apresentada no listagem a seguir. 
<using> <namespace1>; 
<using> <namespace2>; 
 
 <public/private/protected> class <NomeDaClasse> 
 { 
 <public/private/protected> <tipo> <atributo1>; 
 <public/private/protected> <tipo> <atributo2>; 
 <public/private/protected> <tipo> <atributoN>; 
 
 <public/private/protected> <tipo retorno> <propriedade1>; 
 <public/private/protected> <tipo retorno> < propriedade2>; 
 <public/private/protected> <tipo retorno> < propriedadeN>; 
 
 <public/private/protected> <tipo retorno> <método1>; 
 <public/private/protected> <tipo retorno> <método2>; 
 <public/private/protected> <tipo retorno> <métodoN>; 
 } 
 
Vamos considerar uma aplicação de exemplo que defina uma classe Pessoa que armazene dados de 
uma pessoa como nome, sexo, idade, peso, altura, data de nascimento e salário, e com estes atributos faça o 
cálculo do índice de massa corporal (IMC) e o aumente do salário da pessoa. 
Nosso programa pode ser qualquer tipo de aplicação .NET (WindowsForms, ASP.NET, etc). E este fará 
acesso a classe Pessoa. 
Dentro do projeto escolhido devemos criar uma classe chamada Pessoa. O listagem a seguir é o código 
de definição da classe Pessoa com seus atributos, propriedades, construtores, métodos e destrutores. 
/// <summary> 
/// Classe representando uma pessoa. 
/// </summary> 
public class Pessoa 
{ 
 private string _nome; 
 
 /// <summary> 
 /// Configura ou recupera o nome da pessoa. 
 /// </summary> 
 public string Nome 
 { 
 get { return _nome; } 
 set { _nome = value; } 
 } 
 
 private EnumSexo _sexo; 
 
 /// <summary> 
 /// Configura ou recupera o sexo da pessoa. 
 /// </summary> 
 public EnumSexo Sexo 
 { 
 get { return _sexo; } 
 set { _sexo = value; } 
21 
 
 } 
 
 private int _idade; 
 
 /// <summary> 
 /// Recupera a idade da pessoa. 
 /// </summary> 
 public int Idade 
 { 
 get { return _idade; } 
 } 
 
 private double _peso; 
 
 /// <summary> 
 /// Configura ou recupera o peso da pessoa. 
 /// </summary> 
 public double Peso 
 { 
 get { return _peso; } 
 set { _peso = value; } 
 } 
 
 private double _altura; 
 
 /// <summary> 
 /// Configura ou recupera a altura da pessoa. 
 /// </summary> 
 public double Altura 
 { 
 get { return _altura; } 
 set { _altura = value; } 
 } 
 
 private DateTime _dataNascto; 
 
 /// <summary> 
 /// Configura ou recupera a data de nascimento da pessoa. 
 /// </summary> 
 public DateTime DataNascto 
 { 
 get { return _dataNascto; } 
 set 
 { 
 _dataNascto = value; 
 _idade = CalcularIdade(DateTime.Now); 
 } 
 } 
 
 private double _salario; 
 
 /// <summary> 
 /// Configura ou recupera o salário da pessoa. 
 /// </summary> 
 public double Salario 
 { 
 get { return _salario; } 
 set { _salario = value; } 
 } 
 
 
 /// <summary> 
 /// Construtor: Inicializa o objeto (Sobrecarregado) 
 /// </summary> 
 /// <param name="nome">Nome da pessoa</param> 
 /// <param name="sexo">Sexo da pessoa</param> 
 /// <param name="peso">Peso da pessoa</param> 
 /// <param name="altura">Altura da pessoa</param> 
 /// <param name="dataNascto">Data de nascimetno da pessoa</param> 
 /// <param name="salario">Salário da pessoa</param>/// 
 public Pessoa(string nome, EnumSexo sexo, double peso, double altura, DateTime dataNascto, double salario) 
 { 
 _nome = nome; 
 _sexo = sexo; 
 _peso = peso; 
 _altura = altura; 
 _dataNascto = dataNascto; 
22 
 
 _idade = CalcularIdade(DateTime.Now); 
 _salario = salario; 
 } 
 
 /// <summary> 
 /// Construtor padrão (Sobrecarregado) 
 /// </summary> 
 public Pessoa() 
 { 
 _nome = ""; 
 _sexo = EnumSexo.Masculino; 
 _idade = 0; 
 _peso = 0; 
 _altura = 0; 
 _dataNascto = DateTime.Now; 
 _salario = 0; 
 
 } 
 
 /// <summary> 
 /// Retorna o IMC da pessoa quando peso e altura são informados 
 /// </summary> 
 /// <returns>Valor do IMC</returns> 
 public double IMC() 
 { 
 if ((Altura > 0) && (Peso > 0)) 
 { 
 return (Peso / System.Math.Pow(Altura, 2)); 
 } 
 
 return (0); 
 } 
 
 /// <summary> 
 /// Retorna a classificação do peso da pessoa conforme o cálculo do IMC. 
 /// </summary> 
 /// <returns></returns> 
 public string IMCClassificacao() 
 { 
 double imc = IMC(); 
 string retorno = "Seu IMC é " + imc.ToString("N2") + ". "; 
 
 if (imc < 18.5) 
 retorno += "Você está abaixo do peso ideal."; 
 
 else if (imc <= 24.9) 
 retorno += "Parabéns. Você está em seu peso normal!"; 
 
 else if (imc <= 29.9) 
 retorno += "Você está acima de seu peso (sobrepeso)."; 
 
 else if (imc <= 34.9) 
 retorno += "Obesidade grau I."; 
 
 else if (imc <= 39.9) 
 retorno += "Obesidade grau II."; 
 
 else 
 retorno += "Obesidade grau III. Procure um médico."; 
 
 return (retorno); 
 
 } 
 
 /// <summary> 
 /// Calcula a idade da pessoa. 
 /// </summary> 
 /// <param name="dataReferencia">Data em que se quer saber a idade da pessoa.</param> 
 /// <returns></returns> 
 protected int CalcularIdade(DateTime dataReferencia) 
 { 
 int idade = dataReferencia.Year - this._dataNascto.Year; 
 
 return (idade); 
 } 
 
 /// <summary> 
23 
 
 /// Aumenta o salário conforme o percentual informado. 
 /// </summary> 
 /// <param name="percentualAumento">Percentual de aumento do salário.</param> 
 /// <param name="novoSalario">Retorna o novo salário após o aumento.</param> 
 public void AumentarSalario(double percentualAumento, out double novoSalario) 
 { 
 novoSalario = this._salario + (this._salario * (percentualAumento / 100)); 
 this.Salario = novoSalario; 
 } 
 
 /// <summary> 
 /// Aumenta o salário da pessoa conforme o valor informado. 
 /// </summary> 
 /// <param name="valorGratificacao">Entrada: valor do aumento de salário; Saída: novo salário com aumento</param> 
 public void AumentarSalario(ref double valorGratificacao) 
 { 
 valorGratificacao = this._salario + valorGratificacao; 
 this.Salario = valorGratificacao; 
 } 
 
 
 /// <summary> 
 /// Destrutor 
 /// </summary> 
 ~Pessoa() 
 { 
 
 } 
} 
Classe Pessoa. 
Após implementação da classe Pessoa é possível instanciá-la. Dentro do projeto utilize algum recurso 
de interface de usuário para instanciar. Uma classe é instanciada por meio da palavra reservadanew. A sintaxe 
básica para criar um objeto a partir de uma classe é Classe objeto = new Classe(); 
A classe Pessoa tem dois construtores, o primeiro é o construtor padrão que não recebe parâmetros, 
enquanto o segundo permite inicializar o objeto com alguns parâmetros. Vejamos os exemplos a seguir. 
 
Pessoa pessoa = new Pessoa(); 
 
Classe Pessoa instanciada com seu construtor padrão. 
 
Pessoa pessoa = new Pessoa("André", EnumSexo.Masculino, 72, 1.82, 09/09/1981, 10000.00); 
 
Classe Pessoa instanciada com construtor sobrecarregado. 
Utilizando Construtores 
As classes podem apresentar métodos especiais chamados de construtores. Os construtores são 
métodos especiais capazes de inicializar a classe com algum valor. O método construtor pode ser identificado 
por um método com o mesmo nome da classe. 
O construtor é chamado sempre que instanciamos uma classe utilizando o comando new. Uma classe 
pode ter diversos construtores, cada um com uma assinatura diferente. 
Na classe Pessoa temos dois construtores, um construtor padrão que não possui parâmetros 
(assinatura 1), e um segundo com parâmetros que inicializam os atributos da classe (assinatura 2). Vejamos o 
trecho de código a seguir retirado da classe Pessoa. 
 /// <summary> 
 /// Construtor: Inicializa o objeto (Sobrecarregado) 
 /// </summary> 
24 
 
 /// <param name="nome">Nome da pessoa</param> 
 /// <param name="sexo">Sexo da pessoa</param> 
 /// <param name="peso">Peso da pessoa</param> 
 /// <param name="altura">Altura da pessoa</param> 
 /// <param name="dataNascto">Data de nascimetno da pessoa</param> 
 /// <param name="salario">Salário da pessoa</param>/// 
 public Pessoa(string nome, EnumSexo sexo, double peso, double altura, DateTime dataNascto, double salario) 
 { 
 _nome = nome; 
 _sexo = sexo; 
 _peso = peso; 
 _altura = altura; 
 _dataNascto = dataNascto; 
 _idade = CalcularIdade(DateTime.Now); 
 _salario = salario; 
 } 
 
 /// <summary> 
 /// Construtor padrão (Sobrecarregado) 
 /// </summary> 
 public Pessoa() 
 { 
 _nome = ""; 
 _sexo = EnumSexo.Masculino; 
 _idade = 0; 
 _peso = 0; 
 _altura = 0; 
 _dataNascto = DateTime.Now; 
 _salario = 0; 
 
 } 
Utilizando Destrutores 
Quando o garbage collector faz o processo de desalocação dos objetos, podemos fazer com 
que uma função seja executada antes que o objeto seja eliminado. Estas funções são chamadas funções 
destrutoras. Em geral utilizamos estas funções para destruirmos instâncias de objetos não gerenciáveis, tendo 
em vista que o framework não tem controle sobre este tipo de objeto. 
A implementação de um destrutor é semelhante a sintaxe utilizada para construirmos um construtor, 
com a diferença que devemos utilizar o símbolo “~” na frente da declaração. O exemplo a seguir mostra o 
destrutor da classe Pessoa, que neste caso está vazio, ou seja, sem implementação, pois não houve 
necessidade. 
 /// <summary> 
 /// Destrutor 
 /// </summary> 
 ~Pessoa() 
 { 
 
 } 
 
Poderíamos ter uma classe que faz uso de um objeto COM (componente VB6). Este objeto aloca uma 
série de recursos não gerenciáveis que são utilizados durante a execução de métodos da classe. Para 
garantirmos que os recursos deste objeto COM sejam liberados devemos implementar um destrutor para a 
classe, de forma a liberar qualquer recurso alocado pela classe COM. 
Propriedades 
Propriedades são métodos que protegem (encapsulam) o acesso a membros da classe, ou seja, separa 
os elementos visíveis de um objeto dos invisíveis. Todos os atributos da classe Pessoa exemplificada 
anteriormente foram encapsulados, ou seja, protegidos por meio das suas respectivas propriedades. 
25 
 
O código a seguir foi retirado da classe Pessoa que declara o atributo _nome como privado, ou seja, 
somente é acessado diretamente pela classe. Externamente (fora da classe) o atributo pode ser acessado pela 
propriedade Nome. As palavras reservadas get, e set indicam que a propriedade pode recuperar (get) o 
valor do atributo _nome e receber (set) um novo valor. 
 private string _nome; 
 
 /// <summary> 
 /// Configura ou recupera o nome da pessoa. 
 /// </summary> 
 public string Nome 
 { 
 get { return _nome; } 
 set { _nome = value; } 
 } 
 
Modificadores de acesso 
Os modificadores de acesso dizem ao compilador a forma como classe e seus membros podem ser 
acessados externamente. Veja na tabela a seguir os modificadores: 
Modificadores de Acesso - CLASSES 
Modificador Tipo de Acesso 
Public Permite que a classe seja acessada por qualquer assemblie. 
Selead Não permite que a classe seja herdada. 
Partial Permite que a classe tenha seu escopo dividido em vários arquivos. 
Static Especifica que a classe somente tem membros estáticos. Não pode ser instanciada. 
Abstract Define moldes para classes filhas. Não pode ser instanciada. 
Modificadores de Acesso – MEMBROS DA CLASSE 
Modificador Tipo de Acesso 
Public Permite que os membros das classes sejam acessados por qualquer outro escopo 
Protected Permite que membros sejam usados apenas pela classe que o contém e permite que 
estes sejam “herdados” para classes derivadas da original. 
Private O membro é de uso exclusivo da classe onde é declarado. 
Internal Permite acesso somente por classes do mesmo assemblie. 
Static Permite acesso, sem necessidade do objeto ser instanciado. 
Abstract São métodos de classes Abstract que não possuem implementação (sem codificação). 
Virtual Permite que os métodos sejam sobrescritos por classes filhas. 
Readonly Limita acesso a somente leitura aos atributos da classe 
 
Quando o modificador de acesso não é especificado para atributos, o compilador assume o 
modificador private como padrão. Para classes o modificador padrão é public. 
Métodos e passagem de parâmetros 
No C# os métodos são análogos a funções e procedimentos em outras linguagens de programação 
como C e Pascal. 
Um método pode ter variáveis locais, que são variáveis declaradas “dentro” do método e só podem 
ser utilizadas (escopo) apenas dentro do método onde foram declaradas. Os parâmetros do método também 
são locais a ele. 
Inicialmente é preciso informar o tipo de visibilidade do método por meio dos modificadores de acesso 
a membros (visto anteriormente). Logo após é necessário informar o seu tipo de retorno. Caso o método não 
26 
 
tenha nenhum retorno (o que é equivalente as sub-rotinas em outras linguagens) deverá ser utilizada a 
palavra reservada void. Em seguida é dado um nome ao método, e entre parênteses, o conjunto de 
parâmetros aceitos pelo método, se necessário. 
 Os parâmetros são declarados da mesma forma que as variáveis (tipo de dado seguido do nome do 
parâmetro) e devem ser separados por vírgula. Após a declaração dos parâmetros devemos então informar o 
corpo do método entre chaves. Para métodos que retornam algum valor é obrigatório informar a cláusula 
return com o valor de retorno dentro do corpo do método. 
Vejamos alguns exemplos. 
 
//Método simples, sem retorno e sem parâmetros (Equivalente a procedimentos em outras linguagens) 
protected void NomeDoMetodo() 
{ 
 
} 
 
//Método sem retorno e com parâmetros (Equivalente a procedimentos com parâmetros em outras 
linguagens). 
protected void NomeDoMetodo(string param1, int param2) 
{ 
 
} 
 
//Método que retorna uma string e com parâmetros. (Equivalente a função em outras linguagens). 
 protected string NomeDoMetodo(string param1, int param2) 
{ 
 
 return(“string de retorno”); 
} 
 
O código cima apresenta três métodos, o primeiro sem retornoe sem parâmetros, o segundo sem 
retorno e com parâmetros e o último com retorno e parâmetros. 
A classe Pessoa usada como exemplo apresenta 3 métodos, IMC, IMCClassificacao e AumentarSalario, 
sendo este último sobrecarregado duas vezes. O primeiro retorna o valor do IMC, o segundo retorna a 
classificação do IMC da pessoa, e o último aumenta o salário da pessoa conforme os parâmetros da assinatura 
do método. 
Também apresenta um quarto método protegido, CalcularIdade, recebendo como parâmetro uma 
data de referência para o cálculo da idade da pessoa. 
 /// <summary> 
 /// Retorna o IMC da pessoa quando peso e altura são informados 
 /// </summary> 
 /// <returns>Valor do IMC</returns> 
 public double IMC() 
 { 
 if ((Altura > 0) && (Peso > 0)) 
 { 
 return (Peso / System.Math.Pow(Altura, 2)); 
 } 
 
 return (0); 
 } 
 
 /// <summary> 
 /// Retorna a classificação do peso da pessoa conforme o cálculo do IMC. 
 /// </summary> 
 /// <returns></returns> 
 public string IMCClassificacao() 
 { 
27 
 
 double imc = IMC(); 
 string retorno = "Seu IMC é " + imc.ToString("N2") + ". "; 
 
 if (imc < 18.5) 
 retorno += "Você está abaixo do peso ideal."; 
 
 else if (imc <= 24.9) 
 retorno += "Parabéns. Você está em seu peso normal!"; 
 
 else if (imc <= 29.9) 
 retorno += "Você está acima de seu peso (sobrepeso)."; 
 
 else if (imc <= 34.9) 
 retorno += "Obesidade grau I."; 
 
 else if (imc <= 39.9) 
 retorno += "Obesidade grau II."; 
 
 else 
 retorno += "Obesidade grau III. Procure um médico."; 
 
 return (retorno); 
 
 } 
 
 /// <summary> 
 /// Calcula a idade da pessoa. 
 /// </summary> 
 /// <param name="dataReferencia">Data em que se quer saber a idade da pessoa.</param> 
 /// <returns></returns> 
 protected int CalcularIdade(DateTime dataReferencia) 
 { 
 int idade = dataReferencia.Year - this._dataNascto.Year; 
 
 return (idade); 
 } 
 
 /// <summary> 
 /// Aumenta o salário conforme o percentual informado. 
 /// </summary> 
 /// <param name="percentualAumento">Percentual de aumento do salário.</param> 
 /// <param name="novoSalario">Retorna o novo salário após o aumento.</param> 
 public void AumentarSalario(double percentualAumento, out double novoSalario) 
 { 
 novoSalario = this._salario + (this._salario * (percentualAumento / 100)); 
 this.Salario = novoSalario; 
 } 
 
 /// <summary> 
 /// Aumenta o salário da pessoa conforme o valor informado. 
 /// </summary> 
 /// <param name="valorGratificacao">Entrada: valor do aumento de salário; Saída: novo salário com aumento</param> 
 public void AumentarSalario(ref double valorGratificacao) 
 { 
 valorGratificacao = this._salario + valorGratificacao; 
 this.Salario = valorGratificacao; 
 } 
 
Os modificadores in/out/ref 
Quando criamos parâmetros em métodos do C#, estes parâmetros são passados por padrão como 
valores (in), ou seja, se estes valores forem alterados durante a execução do método, a mudança destes 
valores não será refletida na variável passada por parâmetro. Este comportamento é atribuído ao modificador 
de parâmetro in, que é implícito e não precisa ser informado. O exemplo abaixo extraído da classe Pessoa 
utiliza passagem de parâmetros por valor. 
 /// <summary> 
 /// Calcula a idade da pessoa. 
 /// </summary> 
 /// <param name="dataReferencia">Data em que se quer saber a idade da pessoa.</param> 
 /// <returns></returns> 
28 
 
 protected int CalcularIdade(DateTime dataReferencia) 
 { 
 int idade = dataReferencia.Year - this._dataNascto.Year; 
 
 return (idade); 
 } 
 
No exemplo acima, mesmo que o parâmetro dataReferencia fosse alterado dentro do método seu 
valor externamente não seria modificado. Este comportamento pode ser alterado utilizado os moficadores 
ref e out. 
O modificador ref 
O parâmetro ref permite a passagem de valores por referência. Utilizando a passagem de valores por 
referência, os valores modificados dentro da função refletem suas alterações para a função chamadora. Para 
utilizarmos o operador ref, devemos informá-lo tanto na declaração do parâmetro como também na 
chamada do método. Necessariamente o uso do ref requer que a variável a ser passada como parâmetro seja 
inicializada antes de passar sua referência. Vejamos um exemplo. 
 
 ... 
 
 double gratificacao = 1000.00; 
 pessoa.AumentarSalario(ref gratificacao); 
 
 ... 
 
 /// <summary> 
 /// Aumenta o salário da pessoa conforme o valor informado. 
 /// </summary> 
 /// <param name="valorGratificacao">Entrada: valor do aumento de salário; Saída: novo salário com aumento</param> 
 public void AumentarSalario(ref double valorGratificacao) 
 { 
 valorGratificacao = this._salario + valorGratificacao; 
 this.Salario = valorGratificacao; 
 } 
O modificador out 
A diferença entre o modificador out e o ref é que o out permite a passagem de uma variável não 
inicializada por parâmetro, o que não é permitido em parâmetros ref. Veja o exemplo a seguir. 
 
 ... 
 
 double novoSalario; 
 pessoa.AumentarSalario(double.Parse(20, out novoSalario); 
 
 ... 
 
 /// <summary> 
 /// Aumenta o salário conforme o percentual informado. 
 /// </summary> 
 /// <param name="percentualAumento">Percentual de aumento do salário.</param> 
 /// <param name="novoSalario">Retorna o novo salário após o aumento.</param> 
 public void AumentarSalario(double percentualAumento, out double novoSalario) 
 { 
 novoSalario = this._salario + (this._salario * (percentualAumento / 100)); 
 this.Salario = novoSalario; 
 } 
 
 
29 
 
Quando utilizamos o modificador out, a variável deve obrigatoriamente ser inicializada dentro da 
função que contem o parâmetro out. 
Herança 
A herança é um conceito extremamente utilizado dentro do .NET Framework. Este conceito é utilizado 
quando precisamos que uma determinada classe tenha todas as características de outra classe com algumas 
modificações em seu comportamento, ou mesmo algumas funcionalidades adicionais. 
No C# é possível uma classe suportar somente uma herança. Portanto, podemos especificar somente 
uma classe base numa classe filha. A herança múltipla é conquistada através do uso de interfaces. 
using System; 
public class ClassePai 
{ 
 public ClassePai() 
 { 
 Console.WriteLine("Construtor da Classe Pai."); 
 } 
 
 public void Imprimir () 
 { 
 Console.WriteLine("Eu sou a Classe Pai."); 
 } 
} 
 
 
using System; 
public class ClasseFilha : ClassePai 
{ 
 public ClasseFilha() 
 { 
 Console.WriteLine("Construtor da Classe Filha."); 
 } 
} 
 
public class Program 
{ 
 public static void Main() 
 { 
 ClasseFilha classeFilha = new ClasseFilha(); 
 classeFilha. Imprimir(); 
 Console.ReadKey(); 
 } 
} 
Listagem 1: Herança em C#. 
A Listagem 1 mostra duas classes. A primeira classe é chamada ClassePai (base), a segunda é a 
ClasseFilha que herda a ClassePai. Veja que na assinatura da classe ClasseFilha é estabelecida a herança com a 
ClassePai através do “:”. 
 
public class ClasseFilha : ClassePai 
 
O exemplo da Listagem 1 representado graficamente fica assim: 
30 
 
 
Depois de estabelecida a herança, a classe derivada tem exatamente as mesmas capacidades da classe 
base. Portanto, pode-se dizer, a ClasseFilha "é" umaClassePai. Isso é demonstrado no método Main da classe 
Program. A ClasseFilha não tem o seu próprio método Imprimir, por isso usa o método Imprimir da ClassePai. 
A classe base é automaticamente instanciada antes de suas classes derivadas. Isso pode ser constatado 
observando o resultado da saída do exemplo da Listagem 1, onde o construtor da ClassePai é o primeiro a ser 
executado, e depois o construtor da ClasseFilha. 
Pode haver a necessidade de se criar uma nova implementação de um método existente na classe 
base, o que é totalmente possível de se fazer. Na Listagem 2 a classe ClasseFilha declara seu próprio método 
Imprimir e ainda faz uma chamada ao método Imprimir da classe base através da palavra reservada base. 
Observe uma pequena mudança na assinatura do método Imprimir da ClasseFilha, agora temos a palavra 
reservada new indicando uma nova implementação do método Imprimir da ClassePai. 
using System; 
public class ClassePai 
{ 
 public ClassePai() 
 { 
 Console.WriteLine("Construtor da Classe Pai."); 
 } 
 
 public void Imprimir() 
 { 
 Console.WriteLine("Eu sou a Classe Pai."); 
 } 
} 
 
 
using System; 
public class ClasseFilha : ClassePai 
{ 
 public ClasseFilha() 
 { 
 Console.WriteLine("Construtor da Classe Filha."); 
 } 
 
 public new void Imprimir() 
 { 
 base. Imprimir(); //Invoca o método Imprimir da classe base 
 Console.WriteLine("Eu sou a Classe Filha."); 
 } 
 
} 
 
public class Program 
{ 
31 
 
 public static void Main() 
 { 
 ClasseFilha classeFilha = new ClasseFilha(); 
 classeFilha. Imprimir(); 
 Console.ReadKey(); 
 } 
} 
Listagem 2: Invocando método da classe base. 
As classes que herdam características de outras classes podem precisar alterar propriedades ou 
mesmo chamar métodos que estão disponíveis na classe base, como ocorreu no exemplo da Listagem 2. Isto é 
perfeitamente possível caso tenhamos estes métodos ou propriedades com visibilidade public ou 
protected. Porém se estes métodos possuírem visibilidade private, poderão ser vistos apenas na classe 
base e a classe filha não poderá ter acesso a estes valores. 
Polimorfismo 
Polimorfismo é o princípio pelo qual duas ou mais classes derivadas de uma mesma classe base podem 
invocar métodos que tenham a mesma identificação (assinatura) mas comportamentos diferentes, 
especializados para cada classe derivada, usando para tanto uma referência a um objeto do tipo da classe 
base. 
Antes de verificarmos como o polimorfismo funciona sob o ponto de vista do usuário da classe, vamos 
ver como podemos implementar comportamentos diferentes para um mesmo métodos na classe base e na 
classe filha. 
using System; 
public class ClassePai 
{ 
 public ClassePai() 
 { 
 Console.WriteLine("Construtor da Classe Pai."); 
 } 
 
 public virtual void Imprimir() 
 { 
 Console.WriteLine("Eu sou a Classe Pai."); 
 } 
} 
using System; 
public class ClasseFilha1 : ClassePai 
{ 
 public ClasseFilha1() 
 { 
 Console.WriteLine("Construtor da Classe Filha."); 
 } 
 
 public override void Imprimir() 
 { 
 base.Imprimir(); 
 Console.WriteLine("Eu sou a Classe Filha."); 
 } 
 
} 
using System; 
public class ClasseFilha2 : ClassePai 
{ 
 public ClasseFilha2() 
 { 
 Console.WriteLine("Construtor da Classe Filha 2."); 
 } 
 
 public override void Imprimir() 
32 
 
 { 
 base.Imprimir(); 
 Console.WriteLine("Eu sou a Classe Filha 2."); 
 } 
 
 
} 
using System; 
public class Program 
{ 
 public static void Imprimir(ClassePai classePai) 
 { 
 classePai.Imprimir(); 
 } 
 
 public static void Main() 
 { 
 Console.WriteLine("ClasseFilha 1"); 
 ClasseFilha1 classeFilha1 = new ClasseFilha1(); 
 Imprimir(classeFilha1); 
 
 Console.WriteLine(""); 
 Console.WriteLine("ClasseFilha 2"); 
 ClasseFilha2 classeFilha2 = new ClasseFilha2(); 
 Imprimir(classeFilha2); 
 
 Console.ReadKey(); 
 } 
} 
Listagem 3: Implementação do Polimorfismo. 
O exemplo da Listagem 3 representado graficamente fica assim: 
 
Na Listagem 3, temos a classe base ClassePai, e as classes derivadas (filhas) ClasseFilha1 e ClasseFilha2. 
Observe que ambas as classes derivadas reimplementaram o método Imprimir, ou seja, o método Imprimir 
terá comportamento diferente conforme a classe instanciada (ClasseFilha e/ou ClasseFilha2). Para 
permitirmos que as classes filhas possam alterar o comportamento do método Imprimir da ClassePai 
utilizamos o modificador virtual em sua assinatura na classe ClassePai. 
Até aqui nenhuma novidade, pois na Listagem 2 conseguimos reimplementar o método Imprimir sem 
usar o conceito de polimorfismo. 
Para sobrepormos um método usando o conceito de polimorfismo, na assinatura do método da classe 
derivada deve-se usar o modificador override como na Listagem 3. 
33 
 
A grande novidade está do método estático Imprimir da classe principal Program. Ele recebe como 
parâmetro a um objeto da ClassePai, mas em sua chamada dentro do método Main é passado um das classes 
filhas (ClasseFilha e ClasseFilha2). E no momento de execução do código, o run-time se encarrega de 
selecionar o método Imprimir conforme a classe filha do parâmetro. Utilize o Visual Studio em modo 
Debug e veja na prática o que acontece com o método Imprimir. 
Nada impede de utilizamos diretamente o método Imprimir das classes filhas sem passar pela classe 
base. 
Conversão entre as classes 
Agora que já vimos como funcionam os métodos polimórficos, vamos ver algumas regras relativas a 
conversão de dados de classes base para classes filhas e como esta implementação leva ao conceito de 
polimorfismo. 
Quando construímos uma instância de uma classe especializada (ex. ClasseFilha1) podemos atribuir 
esta instância a uma objeto o tipo da classe base (ClassePai). Isto porque a classe especializada (ClasseFilha1) 
suporta todas as características da classe base, e portanto pode ser armazenada em um objeto deste tipo, 
conforme o exemplo a seguir. 
 ClassePai classePai = new ClassePai(); 
 ClasseFilha1 classeFilha1 = new ClasseFilha1(); 
 
 classePai = classeFilha1; 
Classes Abstratas 
Pode acontecer que ao escrever um método para uma classe base não saibamos como ele será 
implementado. Neste caso, a implementação será feita pela classe que herdar o método (a classe filha). 
Pode acontecer também que um determinado método será sobreposto com certeza na classe filha, 
então, não há a necessidade de sua implementação na classe base. Nestes casos definimos apenas a 
assinatura do método e a definição fica por conta da classe que irá herdar a classe base. 
Estas classes são chamadas classes abstratas, e o método não implementado é chamado de método 
abstrato. 
As classes abstratas não podem ser instanciadas através da palavra chave new, é considerada uma 
classe genérica. Contém métodos abstratos que devem ser implementados nas classes que derivam dela, e 
ainda pode conter métodos virtuais e não-abstratos (implementados). Um método abstrato não apresenta 
implementação na classe base. O exemplo a seguir implementa uma classe abstrata com membros abstratos e 
não-abstratos. 
Using System; 
 
public abstract class Pessoa 
{ 
 public abstract string Nome { get; set; } 
 
 public abstract int Id { get; } 
 
 public abstract void Cadastrar(); 
 
 public virtual void Viajar() 
 { /* Ação */ } 
34 
 
} 
 
O exemplo a seguir deriva a classe abstrata Pessoa do exemplo anterior,

Outros materiais