Projetos de Sistemas Web – C# 1)
Linguagem C# ............................................... .................................................................................................... ................................................................. ............ 2 1.1 Classes ................................................... ........................................................................................................ ................................................................. ............ 4 1.2 Objetos ................................................... ........................................................................................................ ................................................................. ............ 4 1.3 Atributos e Métodos ................................................ ............................................................................................... ............................................... 6 1.4 Método Main ................................................... ....................................................................................................... ....................................................... ... 8 1.5 Comentários ..................................................... ......................................................................................................... ....................................................... ... 9 1.6 Tipos de Dados ................................................ .................................................................................................... ...................................................... 10 1.7 Variáveis ................................................ ..................................................................................................... ............................................................... .......... 11 1.8 Constantes .............................................. ................................................................................................... ............................................................... .......... 14 1.9 Conversões de Tipos de dados.............................................................................. dados................................. ............................................. 14 1.10 Operadores ....................................................... ........................................................................................................... ...................................................... 16 1.11 Ordem dos Operadores ..................................................... ......................................................................................... .................................... 18 1.12 Strings .................................................... ......................................................................................................... ............................................................... .......... 19 1.13 Controle de Fluxo – If-Else .................................................................................. ........................................................................ .......... 22 1.14 Comandos de Repetição ................................................... ....................................................................................... .................................... 23 1.15 Vetores ................................................... ........................................................................................................ ............................................................... .......... 24 1.16 Exceções ................................................ ..................................................................................................... ............................................................... .......... 25 1.17 Herança .................................................. ....................................................................................................... ............................................................... .......... 26 1.18 Métodos Estáticos (Métodos de classe) ........................................................ ................................................................ ........ 29
1
1) Linguagem C# C# é uma linguagem de programação orientada a objetos. A estruturação do programa é semelhante à linguagem Java, com a diferença que muitas das palavras-chave são provenientes da linguagem C++, além disso, C# herda vários conceitos da linguagem C++, como struts, tipos sem sinal e sobrecarga de operadores. Como qualquer linguagem orientada a objetos, C# oferece suporte a encapsulamento, herança e polimorfismo, e no geral, sua sintaxe é muito semelhante à linguagem Java, além de compartilharem muitas outras características. Tanto Java como C# compartilham das seguintes características: Ambas compilam em formado intermediário (há um arquivo intermediário que é interpretado para executar o programa). Usam coleta automática de lixo (as variáveis que não são mais utilizadas são apagadas da memória automaticamente). Todas as classes descendem de Object (há uma superclasse para todas as classes e qualquer programa deve ser uma classe). Não há funções globais nem constantes globais (a linguagem é puramente orientada a objetos). Não há herança múltipla: o Em C++ tem-se tal recurso. o Com isso , simplifica os programas. o Interfaces visam suprir essa falta. Utilizam exceções para manipular erros (os erros na execução do programa são classificados e tratados de acordo com seu tipo). Arrays são saltos verificados (um array é um bloco de memória dividido em posições, porém a verificação automática dos limites ao acessar uma posição no vetor, previne o acesso de uma área de memória fora do vetor). A documentação da própria API pode ser obtida pela documentação do código. (código e documentação da API estão juntas no mesmo arquivo). Ambas utilizam pacotes/namespaces para evitar colisões de tipos (O sistema de fontes distribuídos em diretórios evita conflitos de nomes).
Pode-se citar algumas características próprias da linguagem C#, que são as seguintes: Usa atributos de propriedades (atributos que já têm automaticamente setter e ). getter ). Enumerações como em C++. Struts (estruturas de dados sem métodos). Os métodos são não-virtuais por padrão (ao sobrescrever um método, vale por padrão a versão mais próxima de Object). Usar override para sobreescrever. Sobrecarga de operador (permite criar operadores que manipulam objetos). Operadores de Conversão (permite criar operadores que convertem objetos em outros).
2
Documentação em linha XML (a documentação da API é colocada no código fonte no formato XML, depois a documentação pode ser recuperada concatenando todas as partes XML).
Como visto anteriormente, a linguagem C# contém várias características, porém somente algumas serão estudadas nesse curso, uma vez que o foco dessa disciplina é a integração de C# com Asp.Net . Para se começar a trabalhar com C#, pode-se utilizar o SDK do software Microsoft .NET Framework que está disponível gratuitamente no site da Microsoft . Além disso, pode-se trabalhar com C# diretamente no Microsoft Visual Studio, que será a forma adotada nessa disciplina. Para trabalhar com o SDK, deve-se baixar o SDK do Microsoft .NET Framework , instalá-lo, e executá-lo pelo comando/aplicativo csc.exe que pode ser chamado pela linha de comando. O comando csc /help exibirá as opções e modo de uso do SDK, por exemplo, o comando csc /out:Hello.exe Hello.cs compila um programa C#, onde out é o nome do executável gerado e Hello.cs é o nome do arquivo de código fonte. Para se trabalhar com C# no Visual Studio pode-se compilar e desenvolver os programas no ambiente do próprio Visual Studio. Para criar um aplicativo do tipo console no C# deve-se ir no menu New Project e escolher Console Application e em seguida escrever um nome para o projeto. Selecionar C# como linguagem de programação. Para compilar deve-se apertar F6 e para executar deve-se apertar F5. Esse tipo de projeto é um projeto C# de uma aplicação de console. Ao criar um novo projeto de Console, é criado automaticamente uma classe básica de teste. Ao ser executada, ela exibe uma mensagem e fecha, pois o programa termina. Para manter o programa aberto e ver a mensagem após o término de sua execução, deve-se inserir o comando Console.read() no final do método Main para paralisar a execução enquanto o programa aguarda por uma entrada proveniente do teclado. Existem vários ambientes de desenvolvimento para a linguagem C# na Internet, como a SharpDevelop, que é um editor novo voltado a iniciantes que contem suporte a outras linguagens, como Java. No Visual Studio, aplicativos podem ser desenvolvidos visualmente arrastando componentes. Para se criar um aplicativo Windows dessa forma com C#, deve-se ir no menu File/New Project e selecionar Windows Application. Com isso um formulário será exibido, onde podem ser inseridos componentes da toolbox. Outra utilização de C# é através de scripts que são executados quando ocorrem eventos no browser . O primeiro passo é criar um website que use a linguagem C#. Depois disso, quando o usuário clicar nos botões de submissão dos formulários ou outros eventos, deve-se escrever o código C# que será executado no servidor. Cada tela do site contém um arquivo C# code-behind próprio, que contém uma classe C#, de forma que cada evento da tela está relacionado a um método diferente nessa classe. Tais classes não precisam ter um método Main.
3
1.1 Classes Uma classe é uma entidade/conceito em um programa que contém atributos (seu estado interno) e contém métodos (as operações que ela pode realizar). Um mesmo arquivo de código fonte pode conter a definição de várias classes. A seguir, tem-se um exemplo de declaração de classe: using System; namespace ConsoleApplication1 { class Pessoa { public String nome; public long cpf; public long rg; public int idade; // Construtor da classe Pessoa public Pessoa(String nome1, int idade1, long cpf1, long rg1) { nome = nome1; idade = idade1; cpf = cpf1; rg = rg1; } } }
Nesse exemplo, tem-se: using: indica a importação de outras classes ou pacote contendo várias classes. System é a biblioteca padrão. namespace: indica o pacote (ou diretório) da classe. class: indica que começou a declaração de uma classe. Além disso, indica o nome da classe. Atributos public podem ser acessados fora da classe. Construtor: método que permite criar uma instância. Será visto adiante.
1.2 Objetos Como visto anteriormente, uma classe define uma entidade no programa. Porém a declaração de uma classe num arquivo de código fonte é apenas uma definição estática, ou seja, a classe pessoa apenas indica tudo o que é relevante sobre uma pessoa, sem especificar as diversas pessoas do sistema. Um objeto é uma instância de uma classe, portanto, cada objeto é uma pessoa diferente no sistema, ou seja, ao criar uma nova pessoa, os seus dados são preenchidos de acordo com os atributos que estão especificados na classe. A figura a seguir é um exemplo de classe e objeto.
4
Abaixo tem-se a classe Pessoa. A classe Pessoa contém quatro atributos, que são nome, cpf, rg e idade. Logo a seguir, têm-se duas instâncias da classe Pessoa, que são Instancia1 e Instancia2, que são objetos. Cada uma dessas instâncias é um objeto distinto, porém compartilham a mesma classe, ou seja, compartilham as mesmas definições. Pode-se ter infinitas instâncias de uma mesma classe e cada instância vai ser um objeto diferente, ou seja, ele ocupa um espaço de memória próprio para si. Considere o exemplo do cadastro de cliente de uma grande organização que tem centenas de clientes. A classe será a definição estrutural de cada cliente no programa e os objetos corresponderão a cada cliente cadastrado na organização.
Exercício 1 (com base na revisão em aula):
Crie um novo projeto de console C# e crie uma classe chamada Pessoa no arquivo cs que foi criado. Além de nome, CPF, RG e idade, insira o atributo endereço como String. Na classe pessoa, crie um construtor que permita informar todos os dados de uma pessoa. Crie um método main na classe Pessoa. Esse método deve criar dois objetos pessoa e, em seguida, deve escrever na tela o CPF dos dois objetos. Use o método Console.WriteLine para escrever dados no console. A seguir, o gabarito do exemplo:
// Biblioteca Padrão using System; // Pacote da aplicação (nome do projeto) namespace ConsoleApplication1 { // Definição da classe Pessoa class Pessoa { // Atributos de instância public String nome; public int idade; public long cpf; public long rg;
5
public String endereco; // Construtor da classe Pessoa public Pessoa(String nome1, int idade1, long cpf1, long rg1, String endereco1) { nome = nome1; idade = idade1; cpf = cpf1; rg = rg1; endereco = endereco1; } // Método programa public static void Main(String[] args) { // cria dois objetos da classe Pessoa Pessoa joao = new Pessoa("João", 20, 9999999999, 888888888, "Avenida Independência, 123, Caxias do Sul - RS"); Pessoa paulo = new Pessoa("Paulo", 23, 123456789, 987654321, "Avenida República, 999, Caxias do Sul - RS"); // escreve o cpf de ambos Console.WriteLine(joao.cpf); Console.WriteLine(paulo.cpf); // espera antes de fechar o programa Console.Read(); } } }
1.3 Atributos e Métodos Em uma classe podem ser definidos atributos e métodos. Como visto, os atributos determinam as características ou estado de um objeto. São declarados no corpo da classe, por exemplo, nome, rg, cpf e idade do exemplo anterior. Os métodos são as operações que aquele objeto pode realizar. Os métodos podem ser compreendidos como funções, porém podem alterar apenas os atributos do próprio objeto (ou atributos públicos de qualquer objeto). Um método tem acesso total aos atributos declarados dentro da classe, assim como acesso total a todos os outros métodos da mesma classe. Quando um objeto tenta acessar um atributo de um segundo objeto, o operador ponto é usado para realizar o acesso ao atributo. Sua forma de utilização é objeto ponto atributo (ou método). O operador ponto não é necessário quando um objeto tenta acessar seus próprios atributos. Um método pode alterar o estado interno de um objeto ou retornar dados do objeto. Na criação dos métodos de um projeto de software, para descobrir a classe certa que deve conter um determinado método, deve-se observar a qual entidade no programa que está centrado o significado daquele método. Por exemplo, a classe Pessoa deve conter todas as operações do conceito de pessoa. 6
Os métodos podem receber parâmetros e retornar dados. Por default , um método pode acessar todos os atributos do objeto ao qual está inserido. Os construtores são métodos especiais sem retorno que criam uma instância da própria classe. Um construtor não deve ter retorno e o nome dele deve ser o mesmo nome da classe. Essas características identificam um construtor. Em C# é permitido sobrecarga de construtores, nesse caso, variam os parâmetros entre os diversos construtores, porém eles têm o mesmo nome. Em C#, pode haver sobrecarga de métodos, nesse caso, ocorrem múltiplas ocorrências de um método com o mesmo nome, porém, a sua assinatura (parâmetros) deve ser diferente, ou seja, os parâmetros devem ser diferentes. Quanto ao retorno não conta para definir uma assinatura. Cada método sobrecarregado pode retornar um tipo de dado diferente se desejado. O método Main é o método responsável por executar um programa. Ele será visto adiante. Exercício 2 (com base na revisão em aula):
Crie um novo projeto de console C# e crie uma classe chamada Cachorro no arquivo cs que foi criado. Ela deve ter atributos que identifiquem um cachorro. Na classe cachorro, crie um construtor que permita informar todos os dados de um cachorro. Depois crie um método latir , que deve escrever na tela qual cachorro está latindo. Crie um método comer, que receba como parâmetro uma descrição da comida e escreva na tela o que está comendo. Crie um método main na classe Cachorro. No método main, crie dois cachorros. Ao rodar o programa, ambos os cachorros devem latir e comer alguma coisa. Deve ser verificado no console os métodos que os cachorros executaram. A seguir, o gabarito do exercício:
// biblioteca padrão using System; // pacote (nome do projeto) namespace ConsoleApplication1 { // declaração da classe cachorro class Cachorro { // atributos de cachorro public String nome; public String raca; // construtor da classe cachorro public Cachorro(String nome1, String raca1) { // guarda os parametros dentro do objeto nome = nome1; raca = raca1; }
7
// método latir public void latir() { Console.WriteLine("Cachorro " + nome + " latindo: Au-au"); } // método comer public void comer(String nomeAlimento) { Console.WriteLine("Cachorro " + nome + " comendo: " + nomeAlimento); } // método programa public static void Main(String[] args) { // cria dois objetos distintos Cachorro dipsy = new Cachorro("Dipsy", "Pastor Alemão"); Cachorro boby = new Cachorro("Boby", "Pitbull"); // chamando as operações dipsy.latir(); boby.latir(); dipsy.comer("Ração para Filhote"); boby.comer("Ração para Adulto"); // aguarda o usuário digitar algo. Console.Read(); } } }
1.4 Método Main Quando se deseja executar um programa em C#, deve-se executar o arquivo cs que contém alguma classe executável, ou seja, que contém um método Main. A assinatura do método Main é mais comumente usada como public static void Main(){}. Podem ser passados parâmetros ao método Main, porém recomenda-se utilizar a seguinte forma de parâmetros: string[] args, por permitir receber uma lista de parâmetros. Além disso, o método Main pode retornar void ou int . O exemplo a seguir escreve na tela todos os parâmetros passados ao programa: // biblioteca padrão using System; // pacote (nome do projeto) namespace ConsoleApplication1 { // classe class SayHello { // método programa que recebe um vetor de string static void Main(string[] args)
8
{ // para cada parâmetro no vetor foreach (string arg in args) // escreve o parâmetro na tela Console.WriteLine("Hello " + "{0}", arg); // aguarda entrada do usuário Console.Read(); } } }
Para se passar parâmetros para o programa no Visual Studio, deve-se ir no menu Project e escolher propriedades do projeto (última opção). Escolher a opção debug e preencher command line arguments. Ao invés de retornar void , o método Main pode retornar um valor inteiro (int ). Ao retornar um inteiro, pode-se fazer com que o retorno do programa esteja relacionado com o tipo de finalização do programa, indicando se ocorreu sucesso na execução ou erro, e ainda um código que determina o tipo de erro.
1.5 Comentários Em C#, os comentários de linha simples são escritos com duas barras e os comentários de linhas múltiplas são escritos com barra asterisco, como no exemplo abaixo: Using System; namespace ConsoleApplication1 { class SayHello {
// método main static void Main(string[] args) {
/* para cada parametro arg escreve o parametro na tela */ foreach (string arg in args) Console.WriteLine("Hello " + "{0}", arg);
// espera o usuario digitar uma tecla Console.Read(); } } }
Deve-se comentar sempre os programas desenvolvidos de forma que explique realmente a funcionalidade dos mesmos. A inclusão de comentários ajuda na legibilidade do programa, além de oferecer uma visão de como o programa funciona. Programas complexos com comentários que não explicam a semântica do programa podem se tornar ilegíveis. Outro fator a favor do uso de comentários é que comentários não aumentam o tamanho do executável. 9
Para criar comentários de documentação, deve-se usar os comentários de documentação XML. Através de tais comentários, pode-se criar uma documentação da API voltada ao código fonte, semelhante a Java com Javadoc. Essa documentação é gerada no formato XML e pode explicar o funcionamento de cada classe, método e membros. Existem várias tags XML suportadas na documentação do código, cada uma tendo uma função específica. A seguir tem-se um exemplo simples de comentário XML: Using System; /// /// /// /// ///
ConsoleApplication é um pacote que contém um objeto simples de teste.
namespace ConsoleApplication1 { class SayHello
1.6 Tipos de Dados Em toda a plataforma .NET é usado o sistema CTS ( commom type system) que permite a conversão automática de tipos de dados entre linguagens quando ocorre troca de dados entre programas de diferentes linguagens do visual studio (aspx, c#, j#, vb e outros). Essas conversões são realizadas automaticamente pela plataforma, por exemplo, quando uma tela aspx chama um método de uma classe C# que tem parâmetros, os parâmetros são automaticamente convertidos de aspx para C#, sem perda de informações, sem o usuário precisar se preocupar com como a conversão é feita. Existem diversos tipos de dados primitivos disponíveis na linguagem C#. Em C#, todos os tipos de dados primitivos provém do namespace system, portanto, deve-se importar S ystem (colocar using System) em todos os programas, dentro do System, por exemplo, bool corresponde à System.Boolean. Os tipos de dados básicos da linguagem C# são os seguintes:
10
1.7 Variáveis Na linguagem C#, todas as variáveis devem ser declaradas antes de serem utilizadas, pois do contrário será informado um erro de compilação ao tentar executar o programa. Além disso, o tipo de cada variável deve ser informado na declaração. Pode-se definir o valor de uma variável na sua declaração. Múltiplas variáveis podem ser declaradas no mesmo comando de declaração. O tipo de uma variável pode ser um tipo básico visto anteriormente, um tipo de classe, sendo no caso uma declaração de objeto e ainda outros tipos, como struts e outros. Para criar um novo objeto, usa-se o comando new. Exercício 3:
Crie um novo projeto de console C# e crie uma classe chamada Coordenada no arquivo cs que foi criado. Ela deve ter atributos de instância x e y inteiros. Crie um construtor para Coordenada. Crie um método Main numa nova classe. No método Main, crie duas coordenadas e escreva o seu conteúdo. Use variáveis locais para criar o conteúdo das duas coordenadas.
A seguir o gabarito do exemplo: Using System; using System.Collections.Generic; using System.Text; namespace ConsoleApplication1 {
11
// Classe coordenada public class Coordenada { // variavel de instancia x e y public int x, y; // construtor que inicializa a instancia public Coordenada(int x1, int y1) { x = x1; y = y1; } } // classe programa public class Programa { // método programa public static void Main(String[] args) { // criando variaveis locais a b e c int a = 1, b = 2, c = 3; // criando objetos c1 e c2 Coordenada c1 = new Coordenada(a, b); Coordenada c2 = new Coordenada(3, 4*c); // escrevendo as variaveis de instancia da classe Coordenada Console.WriteLine("c1(x,y)=(" + c1.x + "," + c1.y + "): variáveis de instância de c1"); Console.WriteLine("c2(x,y)=(" + c2.x + "," + c2.y + "): variáveis de instância de c2"); Console.Read(); } } }
Nesse exemplo, há dois grupos de variáveis, no primeiro grupo, situado logo após a declaração da classe, são declaradas as variáveis de instância x e y ao simultaneamente. No segundo grupo, logo após a primeira linha do método Main, são declaradas três variáveis a, b, e c com valores inicializados. Existe uma diferença entre esses grupos de variáveis que é comentada a seguir: Há três tipos de variáveis (quanto ao escopo): Variáveis de Instância: É uma variável que pertence à instância, ou seja, toda a instância tem uma cópia daquela variável. Ela é declarada no corpo da classe e cada vez que uma instância é criada, ela é inicializada. Corresponde a x e y no exemplo anterior. Variáveis Locais: Uma variável local é uma variável que é declarada dentro de um método. Ela só existe durante a execução do método (a não ser que seja guardada), portanto quando o método for chamado, aquela variável é instanciada e inicializada, e quando o método acabar, aquela variável é destruída. Corresponde à a, b e c no exemplo anterior.
12
Variáveis de Classe: São variáveis que pertencem à classe e não à instância, ou seja, a variável é única para todas as instâncias e não precisa haver uma instância para a variável existir, apenas a classe. Tais variáveis são inicializadas apenas quando a classe é carregada pela primeira vez. Elas são declaradas da mesma forma que as variáveis de instância, com a diferença que elas contém o prefixo static.
A visibilidade de variáveis pode ser alterada através dos modificadores de acesso. Em C#, tem-se as seguintes combinações de modificadores de acesso. internal: O acesso à variável é limitado para o projeto local. private: O acesso à variável é limitado para apenas dentro da classe que a contém. protected : O acesso à variável é limitado à classe. protected internal: O acesso à variável é limitado á classe ou projeto local. public: O acesso à variável é irrestrito.
Quando uma variável é declarada, ela é inicializada com o valor default daquele tipo. Uma exceção a essa regra é que as variáveis locais nunca são inicializadas automaticamente, elas devem ser inicializadas manualmente no código. Isso ocorre por que espera-se que as variáveis locais sejam usadas em seu escopo, que é limitado. As variáveis do tipo objeto são inicializadas com null. A seguir, há um exemplo com uma melhoria sobre o código anterior. Com o uso de uma variável de classe qtde, é contado o número de instâncias da mesma classe. Sempre antes de criar um novo objeto, o programa escreve a quantidade de instâncias da classe Coordenada. using System; using System.Collections.Generic; using System.Text; namespace ConsoleApplication1 { // Classe coordenada public class Coordenada { // variavel de instancia x e y public int x, y; // variavel de classe que indica a quantidade de instancias public static int qtde = 0; // construtor que inicializa a instancia public Coordenada(int x1, int y1) { x = x1; y = y1; qtde = qtde + 1; } } // classe programa public class Programa
13
{ // método programa public static void Main(String[] args) { // criando variaveis locais a b e c int a = 1, b = 2, c = 3; // escreve 0 por que não há instâncias ainda Console.WriteLine(Coordenada.qtde); // escreve 1 por que foi criada uma instância Coordenada c1 = new Coordenada(a, b); Console.WriteLine(Coordenada.qtde); // escreve 2 por que foi criado duas instâncias Coordenada c2 = new Coordenada(3, 4*c); Console.WriteLine(Coordenada.qtde); // aguarda o usuario apertar enter Console.Read(); } } }
1.8 Constantes Constantes são variáveis cujo valor não pode ser modificado. Elas atuam como qualquer outra variável e são declaradas com o prefixo const . Uma constante deve ser inicializada no momento de sua declaração. Por exemplo: const int d = 5;
1.9 Conversões de Tipos de dados Quando uma variável deve ser atribuída a outra deve-se observar se a atribuição é possível, ou seja, se ambos os tipos são compatíveis, e a variável que recebe deve ter precisão igual ou maior a outra. Em C# tem-se dois tipos de conversões de variáveis: Conversão Implícita: É o caso onde uma variável recebe um valor de precisão menor que a sua, como atribuir um inteiro para um numero real ou, no caso de um byte para um inteiro. Conversão Explícita: É o caso onde um valor é convertido para outro tipo antes de ser atribuído a uma variável. Por exemplo, deve-se converter um inteiro para byte antes de atribuir o valor. Nesse caso, se o valor do inteiro for maior que um byte haverá perda de informação e não será gerado um erro informando essa perda de informação. O programa deve garantir que as operações não sofram perda de dados. As varáveis são convertidas quando é
14
colocado o tipo-destino entre parênteses na frente da variável. Expressões mais complexas para serem convertidas devem estar entre parênteses também. O exemplo abaixo mostra várias conversões: using System; namespace ConsoleApplication1 { class SayHello { static void Main(string[] args) { Teste teste = new Teste(); teste.teste(); Console.Read(); } } class Teste { public void teste() { byte a = 1; // int b = 1234; // int c = a; // double d = b; //
variavel local Byte variavel local Inteira Conversao Implícita Conversao Implícita
Console.WriteLine("c={0}", c); Console.WriteLine("d={0}", d); double e = 5.2344; // Variável Real int f = (int)e; // Conversão Explícita Console.WriteLine("f={0}", f); } } }
Observe, que na declaração da variável c, ocorre uma conversão implícita, pois a variável byte a é atribuída a variável inteira c. Essa é uma conversão de um tipo menor para um tipo maior e é automática, pois a variável inteira pode conter um byte. O mesmo ocorre na linha seguinte, onde um número inteiro é atribuído a um número real. O número real pode conter um inteiro, e a conversão ocorre sem perda de informação. Na declaração da variável f , ocorre uma conversão explícita de double para int . Com essa conversão vai ocorrer perda de informação, ou seja, a parte fracionária da variável e será ignorada. Para ver a perda de informação, veja o resultado do programa:
15
Exercício 4:
Faça um programa que crie uma variável do tipo byte, uma int, uma long, uma float e uma double, e inicialize elas. Nas operações a seguir, utilize casting, caso necessário: Atribua o valor da variável double para uma long. Atribua o valor da variável long para a variável byte. Some todas as variáveis e atribua para uma variável double. Some todas as variáveis e atribua para uma variável long. Imprima na tela o resultado das conversões.
1.10 Operadores Existem diversos tipos de operadores que são oferecidos na linguagem C#. Os principais operadores são:
Operadores Matemáticos: Operador Descrição + Adição Subtração * Multiplicação / Divisão % Resto (Módulo) Principais Operadores de Atribuição: Operador Descrição = Atribuição simples += Atribuição com adição -= Atribuição com subtração *= Atribuição com multiplicação /= Atribuição com divisão %= Atribuição com resto &= Atribuição com AND |= Atribuição com OR Incremento e Decremento:
16
Os operadores de incremento e decremento são respectivamente ++ e --. O operador de decremento aumenta o valor de uma variável em uma unidade, enquanto que o decremento diminui em uma unidade. Os operadores de incremento e decremento são operadores unários, ou seja, precisam de apenas uma variável. Se o operador for colocado antes da variável (prefixado), a primeira coisa que ocorrerá naquela expressão será o incremento, se for colocado após a variável, o incremento ocorrerá após a execução da expressão total. Como exemplo, tem-se: using System; namespace ConsoleApplication1 { class Operators { static void Main() { int a = 10, b, c; b = a++; // operação posfixa c = ++a; // operação préfixa Console.WriteLine("{0}", b); Console.WriteLine("{0}", c); b = b--; c = --c;
// operação posfixa // operação préfixa
Console.WriteLine("{0}", b); Console.WriteLine("{0}", c); Console.Read(); } } }
Que gera a seguinte saída:
Operadores Relacionais: == Igual a != Diferente de < Menor que <= Menor ou igual a > Maior que >= Maior ou igual a
17
Operadores Lógicos && AND lógico || OR lógico ! Negação Lógica Operador Ternário: O operador ternário representa uma estrutura condicional, sendo o equivalente a if-then-else. A forma de utilização do operador ternário exige 3 parâmetros, e tem a seguinte forma: Expressão1 ? Expressão2 : Expressão3
Expressão1 é uma expressão lógica, que resulta em valor true ou false. Expressão2 é uma expressãode qualquer tipo, assim como Expressão3. Quando ao modo de execução do operador ternário, se Expressão1 for verdadeiro, então, o resultado será Expressão2, caso contrário, será Expressao3. Operadores ternários podem ser aninhados também. Um exemplo com uso de operador ternário está a seguir: using System; namespace ConsoleApplication1 { class Operators { static void Main() { int a = 10, b = 5; int c = a==b ? a : b; Console.WriteLine("{0}", c);
// resultado 5
Console.Read(); } } }
1.11 Ordem dos Operadores A ordem dos operadores deve ser observada, pois pode alterar o resultado da expressão. Para se alterar a ordem dos operadores, deve-se usar parênteses. Expressões entre parênteses são executadas primeiro que as outras. A seguir, tem-se a tabela da ordem de execução dos operadores em C#:
18
1.12 Strings Strings são dados alfanuméricos. As literais String são rodeadas por aspas duplas. Uma string é um objeto. Um objeto String é imutável, ou seja, não pode ser alterado. Quando deseja-se alterar uma string, deve-se realizar a operação criando uma nova string e atribuir o resultado a variável desejada. A seguir, um exemplo de uso de String: Using System; namespace ConsoleApplication1 { class ManipulacaoDeStrings { static void Main() {
19
String s = "Hello World"; Console.WriteLine("Programa Teste"); Console.WriteLine(s); Console.Read(); } } }
Como String são objetos, cada String contém todos os métodos da classe String. Tais métodos permitem converter a string, concatenar, comparar e outras operações. Como as strings são imutáveis, a string resultante da operação é retornada ao invés de alterar a string original. Os principais métodos da classe String são: Length: retorna o tamanho da string. [int index]: recupera o caracter da posição index. Concat(String str): concatena esse string a outro e retorna a string total. Compare: permite comparar uma string com outra. ToLower(): converte para lower case. ToUpper(): converte para upper case. Trim(): remove espaços em branco no início e fim do string.
Além disso, as strings podem ser concatenadas com o operador +. As strings possuem alguns caracteres especiais que precisam ser escritos conforme a tabela a seguir: Nova linha Fim de linha Tabulação Barra
\r \n \t \\
Exercício 5:
Faça um programa que tenha a classe Pessoa do Exercício 1. No método Main, crie três pessoas com endereços distintos (sem país). Verifique se a string endereço de cada pessoa contém o nome: “Julio de Castilhos”. Depois disso, concatene ao endereço de cada pessoa o país do endereço. Escreva o endereço de cada objeto na tela.
A seguir, o gabarito do exercício: using System; using System.Text; namespace ConsoleApplication1 { // Definição da classe Pessoa class Pessoa {
20
// Atributos de instância public String nome; public int idade; public long cpf; public long rg; public String endereco; // Construtor da classe Pessoa public Pessoa(String nome1, int idade1, long cpf1, long rg1, String endereco1) { nome = nome1; idade = idade1; cpf = cpf1; rg = rg1; endereco = endereco1; } public static void Main(String[] args) { // criando três objetos pessoa Pessoa joao = new Pessoa("João", 20, 111, 123, "Avenida Paulista, 2332, Edifício Excalibur, São Paulo, SP"); Pessoa pedro = new Pessoa("Pedro", 21, 121, 134, "Julio de Castilhos, 5233, Edifício Pérola, Caxias do Sul, RS"); Pessoa ademar = new Pessoa("Ademar", 23, 345, 345, "Avenida Independência, 1111, Porto Alegre, RS"); // verifica se a rua é julio de castilhos Console.WriteLine(joao.endereco.Contains("Julio de Castilhos")); Console.WriteLine(pedro.endereco.Contains("Julio de Castilhos")); Console.WriteLine(ademar.endereco.Contains("Julio de Castilhos")); // concatena o país no endereço. // como strings são imutáveis, devem ser criados novos objetos joao.endereco = joao.endereco + ", Brasil"; pedro.endereco = pedro.endereco + ", Brasil"; ademar.endereco = ademar.endereco + ", Brasil"; // escrevendo os novos enderecos Console.WriteLine(joao.endereco); Console.WriteLine(pedro.endereco); Console.WriteLine(ademar.endereco); // espera dgitar enter Console.Read(); } } }
Gerando o seguinte resultado:
21
1.13 Controle de Fluxo – If-Else Para desviar o fluxo de execução do programa, pode-se usar a instrução if-else. A instrução if testa uma afirmação lógica (valor booleano). Se o resultado for verdadeiro, será executado o bloco de comando do if . Se o resultado for falso, será executado o bloco de comando do else. Um exemplo de uso do comando if é o seguinte: using System; using System.Text; namespace ConsoleApplication1 { public class Pessoa { public String nome; public String endereco; public Pessoa(String nome1, String endereco1) { nome = nome1; endereco = endereco1; } public void testeStrings() { int x = 3; double y = Math.Sqrt(3); if (x >= y) Console.WriteLine("x é maior"); else Console.WriteLine("x é menor");
if (endereco.Contains("Avenida Paulista")) { Console.WriteLine("Endereço na Avenida Paulista"); } else Console.WriteLine("Endereço é em outra rua"); } public static void Main(String[] args) {
22
Pessoa joao = new Pessoa("João", "Avenida Paulista, 2332, Edifício Excalibur, Próximo Livraria Cultura"); joao.testeStrings(); Console.Read(); } } }
Gera o seguinte resultado:
Exercício 6:
Faça um programa em C# que verifica se dois números passados pela linha de comando são múltiplos. O programa deve escrever “são múltiplos” quando forem múltiplos, e caso contrário, “não são múltiplos”.
1.14 Comandos de Repetição Para se executar um determinado bloco de comando várias vezes, deve-se usar os comandos de repetição. O comando mais básico é o while. O comando while executa um determinado bloco de comandos enquanto uma determinada condição for verdadeira. Por exemplo, tem-se o seguinte programa que escreve todos os números menores que 10: using System; using System.Text; namespace ConsoleApplication1 { public class Teste { public static void Main(String[] args) { int x = 0; Console.Write("Números menores que 10:"); while (x < 10) { Console.WriteLine(x); x = x + 1; } Console.Read(); } } }
23
Outro comando é o for . Ele permite iterar entre um determinado intervalo de valores. O exemplo a seguir ilustra o uso do for : using System; using System.Text; namespace ConsoleApplication1 { public class Teste { public static void Main(String[] args) { for (int x = 234; x < 545; x++) { Console.WriteLine(x); } Console.Read(); } } }
A instrução break pode parar um laço de repetição. A instrução continue termina a iteração corrente e inicia a próxima. O comando foreach permite iterar entre todos os elementos de um vetor. O seu uso ocorre da seguinte forma: Using System; namespace ConsoleApplication1 { class SayHello { static void Main(string[] args) { foreach (string arg in args) Console.WriteLine("Hello " + "{0}", arg); Console.Read(); } } }
Exercício 7:
Faça um programa que receba dois números inteiros pela linha de comando e escreva todos os números inteiros que estão entre aqueles dois números.
1.15 Vetores Um vetor armazena uma coleção de valores ou objetos. Todo o vetor tem um tipo (que é o tipo de elementos que ele pode guardar) e um tamanho. As posições no vetor iniciam
24
em zero. O atributo Length retorna o tamanho do vetor. O exemplo a seguir lê 20 strings do teclado e coloca em um vetor com 20 posições. Observe o uso do for : using System; using System.Text; namespace ConsoleApplication1 { public class Teste { public static void Main(String[] args) { String[] nomes = new String[20]; for (int x = 0; x < 20; x++) { nomes[x] = Console.ReadLine(d); } Console.Read(); } } }
Quando um vetor é inicializado, é informado o tamanho do vetor. Seus elementos são criados com o valor default, sendo null para objetos. O próprio vetor é um objeto. Se o vetor não for inicializado na sua declaração, ele terá o valor default null. Matrizes podem ser criadas da mesma forma que vetores, com a diferença que um novo abre-fecha colchetes é adicionado. As dimensões da matriz devem ser informadas na sua inicialização. Exercício 8:
Faça um programa em C# que lê 5 valores inteiros da entrada padrão (Console.read ) e insira os valores em um vetor de 5 posições. Em seguida, o vetor deve ser percorrido para calcular a soma de todos os elementos no vetor. Escrever na tela a soma dos elementos.
1.16 Exceções Quando ocorre um erro no programa, o programa é abortado. Porém, é possível definir tratamento de erros em C# e continuar a execução do programa. O ideal nesses casos, é capturar o erro, tratar da forma adequada mostrando uma mensagem de erro ao usuário e retornar ao fluxo normal do programa, com as devidas correções. Para definir um bloco de código que seja capaz de prever exceções, deve-se usar o comando try-catch. Como a própria exceção é um objeto, existem vários tipos de exceção, pois toda a exceção deriva da classe Exception, sendo assim cada exceção uma classe diferente. O comando finally define um bloco de código de limpeza, que é executado independentemente de uma exceção ter sido lançada ou não. Execute esse programa no Visual Studio para ver o lançamento e a captura da exceção. Nesse programa, é criado um
25
vetor com duas posições, porém ele tenta acessar uma posição além do limite do vetor. Ao fazer isso, é lançada uma exceção do tipo IndexOutOfRangeException. O comando catch define o tratamento da exceção. Using System; namespace ConsoleApplication1 { public class Teste { public static void Main(String[] args) { try { String[] nomes = new String[2]; for (int x = 0; x < 5; x++) { nomes[x] = Console.ReadLine(); } } catch (IndexOutOfRangeException e) { Console.WriteLine("fora do limite do vetor"); } finally { Console.WriteLine("Limpeza"); } Console.Read(); } } }
Em C# é possível criar novas exceções estendendo a classe ApplicationException (por herança). O comando throw permite lançar (ou relançar) exceções. É recomendável criar exceções públicas, para que possam ser manipuladas por outros códigos, dessa forma.
1.17 Herança É a relação entre duas classes na qual uma herda tudo o que a outra contém, ou seja, todos os atributos e métodos que a superclasse tem, a subclasse também tem. Em C#, todos os métodos são virtuais por default , ou seja vale a versão da superclasse. O modificador override permite fazer com que valha a versão da subclasse. Para definir uma relação de herança, deve-se informar a superclasse na definição da classe (com dois pontos). Exemplo de classe com relação de herança: Using System; using System.Text;
26
namespace ConsoleApplication1 { public class Animal { public String nome; public String especie; public Animal(String nome1, String especie1) { nome = nome1; especie = especie1; } public void caminhar() { Console.WriteLine("Animal Caminhando: " + nome); } } public class Gato : Animal { String dono; public Gato(String nome1, String especie1, String dono1) : base(nome1, especie1) { dono = dono1; } public void miar() { Console.WriteLine("Gato Miando: " + nome + ":" + dono); } } public class Teste { public static void Main(string[] args) { Animal a = new Animal("Golfinho", "mamífero"); a.caminhar(); Gato g = new Gato("felix", "felino", "Paulo"); g.caminhar(); g.miar(); Console.Read(); } } }
No construtor de uma subclasse, deve-se colocar o código que inicializa a instância que está sendo criada da subclasse, ou seja, suas personalizações. Ao declarar um construtor de uma subclasse, deve-se chamar o construtor da superclasse antes de qualquer coisa. Usa-se o comando base para definir qual o construtor da superclasse que é chamado na inicialização da subclasse.
27
Public Gato(String nome1, String especie1, String dono1) : base(nome1, especie1)
A relação de herança entre gato e animal estabelece que cada objeto gato também é um objeto animal, mas o contrário não é verdadeiro. public class Gato : Animal //animal: superclasse
Animal é a superclasse a gato é a subclasse. Gato herda todos os métodos e atributos públicos de Animal: Public class Gato : Animal
Veja o resultado da execução do programa anterior:
A palavra this se referente sempre a própria instância, ou seja, ela é a própria instância. Ao retornar this, será retornada a própria instância. Dentro de uma classe, os atributos da instância podem ser acessados também por this.nomeAtributo, que é o mesmo que apenas acessar pelo nome do atributo. Quando é declarada uma variável local cujo nome é igual a uma variável de instância, a variável de instância somente poderá ser acessada através de this, pois a última declaração é a que vale, e a última declaração é a variável local. Recriando a classe Pessoa do primeiro exemplo usando this no construtor, temos o seguinte código: using System; namespace ConsoleApplication1 { class Pessoa { public String nome; public int idade; public long cpf; public long rg; public String endereco; public Pessoa(String nome, int idade, long cpf, long rg, String endereco) {
this.nome = nome; this.idade = idade; this.cpf = cpf; this.rg = rg;
28
this.endereco = endereco; } } }
1.18 Métodos Estáticos (Métodos de classe) São métodos que contém o prefixo static. Como eles são métodos de classe, eles não podem acessar as variáveis de instância da própria classe na qual estão inseridos. Além disso, os métodos estáticos não podem acessar os métodos de instância. Portanto, métodos estáticos apenas podem acessar outros métodos estáticos e variáveis estáticas. Isso ocorre por que dentro de um método estático, não existe instância, logo não existem variáveis e métodos de instância. Uma forma de se acessar tais métodos dentro do método estático, é criar um objeto do mesmo tipo da classe. Agora aqueles métodos poderão ser acessados, mas somente através da instância que foi criada, com operador ponto. O método Main é um exemplo de método estático que não pode acessar variáveis e métodos de instância.
Exercícios:
1. Faça um programa em C# que leia dois números e escreva na tela todos os números inteiros entre os dois números. 2. Faça um programa em C# que leia um número e escreva na tela se o número é primo ou não. 3. Faça um programa que crie uma classe pessoa e uma classe animal. A classe pessoa deve ter o atributo nome e a classe animal deve ter o atributo nome e o atributo especie. Crie uma classe PessoaXAnimal que guarda um objeto pessoa e um animal de estimação, possibilitando assim, uma mesma pessoa ter vários animais de estimação. Crie três objetos pessoa e quatro objetos animal. Defina os donos de todos os animais de estimação criando instâncias da classe PessoaXAnimal. Escreva na tela todos os objetos criados. 4. Faça um programa que leia um vetor de números inteiros do teclado e escreva o maior elemento do vetor. 5. Crie uma classe Animal e uma classe gato e uma classe cachorro que são filhas de Animal. A classe animal deve ter o método comer. Redefina esses métodos nas classes filhas. Escreva na tela os resultados.
29