Tuesday, April 10, 2007

MAIS UMA INTRO À .NET FRAMEWORK 2.0 - Parte I

Introdução

Este artigo foi desenvolvido a partir do meu próprio estudo para o exame de certificação Microsoft Technology Specialist e trata-se, sobretudo, de expor pelas minhas palavras aquilo que assimilei durante este processo.
Tem também referências a trabalhos de outros autores que eu acho que acrescentam valor ao conteúdo aqui exposto, sendo que este artigo é essencialmente baseado no MCTS Self-Paced Training Kit para o exame 70-536 – Microsoft .NET Framework 2.0 —Application Development Foundation.
Um outro objectivo deste artigo é também ajudar todos os que tiverem interesse em efectuar o referido exame mas, por qualquer motivo, tenham decidido não adquirir o livro que está na base deste artigo.

Convenções

Texto em Itálico – Conteúdo em língua estrangeira
Texto em Courier New (10pt) – Conteúdo que representa pedaços de código-fonte

Capítulo 1 - Aspectos Fundamentais da .NET Framework 2.0

A .NET Framework 2.0, resumidamente, é uma plataforma de desenvolvimento de aplicações criada pela Microsoft com um foco muito grande no desenvolvimento de aplicações de um modo rápido (RAD) e com o objectivo de proporcionar uma plataforma independente de linguagem e de plataforma.

Neste capítulo irei introduzir alguns dos aspectos mais básicos da .NET Framework , como Tipos, Atributos e Encapsulação, focando também algumas novidades da .NET Framework 2.0 relativamente à 1.1 e 1.0, como Genéricos, entre outros.

Eu assumo que quem está a ler este artigo tem pelo menos 2 anos de experiência de programação em .NET, independentemente da plataforma.
Todos os exemplos de código neste artigo serão em C#, excepto quando for necessário referir alguma especificidade da Framework que seja diferente em VB.

1. Tipos de Valor

Um dos erros mais comuns que a maioria dos programadores cometem quando aprendem (e programam com) a .NET Framework tem a ver com a confusão que se faz, por um lado, entre Tipos de Valor e Tipos de Referência e, por outro, com a passagem de valores por Referência ou por Valor.

Tipos de Valor são os tipos mais simples que existem na .NET Framework e incluem todos os tipos de dados numéricos, booleanos, Char e Date, estruturas (mesmo que os seus membros sejam Tipos por Referência) e enumerados (uma vez que os seus tipos intrínsecos são sempre Byte, Short, Integer e/ou Long).

1.1. Tipos de Valor Nativos

Estes tipos são os tipos base disponibilizados pela .NET Framework e são a base de construção de outros tipos. Derivam da Classe System.ValueType que, por sua vez, deriva de System.Object.

A principal característica destes tipos tem a ver com o facto de o seu valor estar armazenado na Stack em vez do Heap, ou seja, estão acessíveis mais rapidamente pelo código em excução.

Existem mais de 300 tipos de valor na .NET Framework, mas de entre os mais comuns destacam-se os seguintes:

· Byte – 1 Byte. Armazena valores de bytes entre 0 e 255, sem sinal.
· Sbyte - 1 Byte. Armazena valores de bytes entre -128 e 127.
· Int16 (ou apenas short) – 2 Bytes. Armazena valores inteiros entre – 32768 e 32767.
· Int32 (ou apenas int) -4 Bytes. Armazena valores inteiros entre – 2147483648 e 2147483647.
· Uint32 (uint em C#) - 4 Bytes. Armazena valores inteiros entre 0 e 4294967295, sem sinal.
· Int64 (ou apenas long) -8 Bytes. Armazena valores inteiros entre – 9223372036854776808 e 9223372036854776807.
· Single (float em C#) - 4 Bytes. Armazena valores de vírgula flutuante entre – 3.402823E+38 e 3.402823E+38.
· Double - 8 Bytes. Armazena valores de vírgula flutuante entre – 1.79769313486232E+308 e 1.79769313486232E+308.
· Decimal - 16 Bytes. Armazena valores de vírgula flutuante entre – 79228162514264337593543950335 e 79228162514264337593543950335.
· Char - 2 Bytes. Armazena um único caracter Unicode.
· Boolean (ou apenas bool) - 4 Bytes. Armazena valores verdadeiro/falso.
· DateTime (ou apenas date) - 8 Bytes. Armazena momentos no tempo entre 1/1/0001 e 31/12/9999.

Em tempo de execução, o desempenho dos tipos Int32 (int e uint) são optimizados, por isso é aconselhado o seu uso para contadores e outras variáveis que são utilizadas frequentemente. No caso de operações que necessitem de Tipos de vírgula flutuante, é recomendado o uso de Double, uma vez que o seu desempenho é optimizado ao nível do Hardware.

1.2. Decalaração de Tipos de Valor

Para usar um Tipo de Valor é necessário declarar uma variável do tipo desejado. Estes Tipos possuem um construtor implícito, ou seja, ao declarar uma variável deste tipo estamos a instanciá-la imediatamente. Contudo, é recomendado que este tipo de variáveis seja inicializada logo na sua declaração:


int x = 0;


Uma das funcionalidades novas na .NET Framework 2.0 são os Tipos de Valor Nulos, ou seja, agora é possível criar variáveis de Tipos de Valor que aceitam valores nulos (por exemplo booleanos nulos). Para declarar variáveis de Tipos de Valor que aceitem valores nulos deve usar-se a seguinte sintaxe:


Nullable <int>x = null;
Ou ainda:
int? x = null;


Desta forma evitamos o (mais que) comum erro “Cannot convert null to 'int' because it is a value type”. Ao declararmos uma variável como Nullable torna disponíveis os membros HasValue e Value, que tornam possível determinar se esta variável tem um valor nulo e, no caso de não ter, ler o seu valor.


if (x.HasValue) // Boa, o valor de x não é nulo!
Console.WriteLine(“O valor de x é {0}”), x.Value);
else // Ooops, o valor de x é nulo!
Console.WriteLine(“x é nulo!”);


1.3. Tipos de Valor Definidos pelo Utilizador (Estruturas)

Estruturas (structs) são Tipos de Valor definidos pelo programador, sendo um composto de outros Tipos de Valor que facilitam a utilização de dados inter-relacionados. Tal como os outros Tipos de Valor, são armazenados na Stack, o que os torna bastante eficientes (às vezes mais eficientes que classes). Para se definir estruturas deve fazer-se algo semelhante ao seguinte:


struct SerHumano
{
public float altura;
public float peso;
public short idade;

public SerHumano (float _altura, float _peso, short _idade)
{
altura = _altura;
peso = _peso;
idade = _idade;
}

public override string ToString()
{
return “Este Ser Humano mede “ + altura + " m, pesa " + peso + " kg e tem " + idade + “ anos.”;
}
}


De notar ainda um pormenor. As estruturas não podem ter um Construtor de defeito (sem parâmetros). O motivo tem a ver com o facto de, para Tipos de Valor, o compilador não gera um construtor de defeito nem uma chamada ao construtor de defeito na instanciação. Ou seja, mesmo que definissemos um construtor de defeito, ele não seria chamado. Para evitar isso, o compilador de C# não permite a sua definição.

Contudo, se utilizarmos o código abaixo, não existe uma chamada a um construtor sem parâmetros. Mas o compilador também não rejeita esta instrução. O que acontece é que os campos da Estrutura são todos inicializados a nulo ou zero, através da utilização do Opcode .InitObj do IL (Intermediate Language).


SerHumano k = new SerHumano();


As estruturas devem possuir as seguintes características:
· Representar logicamente um valor único
· Ter um tamanho de instância inferior a 16 Bytes
· Não irão ser alteradas após a sua criação
· Não irão ser convertidas para um Tipo de Referência

1.4. Enumerados

Enumerados (Enums) são tipos especiais de Tipos de Valor. São símbolos relacionados com valores fixos e imutáveis. Ou seja, pode dizer-se que se tratam de constantes com nomes mais facilmente acessíveis.

O seu objectivo é simplificar a programação através da atribuição de nomes a valores fixos de uma lista de possíveis valores. Assim, em vez de se referenciar o seu valor, referencia-se o seu nome, tornando o código mais legível e bem estruturado.


public enum Titulos : int { Sr, Sra, Dr, Dra, Prof };
...
Titulos t = Titulos.Prof;
string name = “José Pedras”;
Console.WriteLine(“{0}. {1}”, t, name);


De seguida (no próximo artigo) irei falar-vos de Tipos por Referência.