Vous êtes sur la page 1sur 96

Introduo

objectivo principal deste capitulo introduzir os conceitos centrais da linguagem C#, incluindo os tipos de dados intrnsecos ( value-based e reference-based); construes de deciso e iterao; mecanismos de boxing e unboxing; e, tcnicas bsicas para construo de classes. Ao longo da exposio, aprenderemos tambm como se manipulam strings, arrays, enumeraes e estruturas. Para ilustrar aqueles fundamentos da linguagem, iremos introduzindo a biblioteca de classes base do .NET, e construiremos um conjunto de aplicaes utilizando os vrios namespaces. Uma vez tendo explicado como se integram os namespaces pr-definidos, este captulo termina mostrando como se organizam tipos especficos em namespaces definidos pelo utilizador.

Autor: Andrew Troelsen Traduo: Carlos Martins

C# and the .NET Platform, 2. C# Language Fundamentals

1 de 96

A Anatomy of a Basic C# Class (1)


Assim como a linguagem Java, o C# obriga a que toda a lgica esteja contida dentro da definio de um tipo (aqui, tipo o nome genrico para nos referirmos a classe, estrutura, etc.). Ao contrrio do C(++) no possvel criar funes ou dados globais usando a linguagem C#. Na sua forma mais simples, uma classe C# pode ser definida do seguinte modo:
// C# class files end with a *.cs file extension using System; class HelloClass { // Oddly enough, Main can be declared as 'private' // if need be... public static int Main(string[] args) { Console.WriteLine("Hello World"); return 0; } }

Definimos um tipo (HelloClass) que suporta um nico mtodo designado Main. Toda as aplicaes C# devem conter uma classe que defina um mtodo Main, considerado pelo CLR como entry point da aplicao. Embora seja tecnicamente possvel que um projecto C# contenha mltiplas classes definindo mtodos Main, necessrio explicitar ao compilador de C# qual o mtodo a usar como entry point da aplicao para que este no emita um erro de compilao.

Autor: Andrew Troelsen Traduo: Carlos Martins

C# and the .NET Platform, 2. C# Language Fundamentals

2 de 96

A Anatomy of a Basic C# Class (2)


A assinatura de Main est adornada com as palavras chave public e static (repare tambm na letra maiscula M em Main, que obrigatria). Adiante neste captulo, daremos a definio formal das palavras chave public e static. At l, consideraremos que os mtodos pblicos so acessveis a partir do mundo exterior, enquanto que os mtodos estticos tm o mbito da classe (no de objecto) e podem, por isso, ser acedidos sem criar nenhuma instncia da classe. Para alm das palavras chave public e static, o mtodo Main tem um parmetro, que um array de string (string[] args). Embora no tenhamos feito nada para manipular este array, este parmetro permite aceder aos argumentos passados na linha de comando. Toda a lgica da classe HelloClass est dentro do mtodo Main. Aqui utiliza-se a classe Console, que definida no namespace System. De entre os vrios membros desta classe existe o mtodo esttico WriteLine que escreve um string no standard output.
// Pump some text to the console Console.WriteLine("Hello World");

Uma vez que o mtodo Main foi definido como devolvendo um inteiro, deve devolver zero (sucesso) antes de terminar. Finalmente, podemos constatar que o C# mantm o formato dos comentrios usado em C e C++.

Autor: Andrew Troelsen Traduo: Carlos Martins

C# and the .NET Platform, 2. C# Language Fundamentals

3 de 96

A Anatomy of a Basic C# Class (3)


Variations on the Main Method
No programa anterior declarmos o mtodo Main() tomando um parmetro (um array de strings) e a devolvendo o tipo inteiro. No entanto, esta no a nica forma de declarar este mtodo. Para alm da assinatura de Main usada no exemplo anterior, possvel definir o mtodo Main de um programa usando uma das seguintes assinaturas:
// No return type, array of strings as argument. public static void Main(string[] args) { // Process command line arguments. // make some objects. } // No return type, no arguments. public static void Main() { // make some objects. } // Integer return type, no arguments. public static int Main() { // make some objects. // Return a value to the system. }

A forma como se define Main tem a ver com a forma como respondemos s duas perguntas seguintes: primeira, necessrio processar argumentos da linha de comando? Em caso afirmativo, estes sero armazenados no array de strings. A seguir, necessrio devolver um valor ao sistema quando Main termina? Em caso afirmativo, aquele mtodo devolve int e no void.
C# and the .NET Platform, 2. C# Language Fundamentals
4 de 96

Autor: Andrew Troelsen Traduo: Carlos Martins

A Anatomy of a Basic C# Class (4)


Processing Command Line Arguments
Assuma que desejamos actualizar a classe HelloClass para processar eventuais argumentos passados na linha de comando (analisaremos a seguir a sintaxe {0} a seguir):
// This time, check if we have been sent any command line arguments. using System; class HelloClass { public static int Main(string[] args) { // Print the args! for (int x = 0; x < args.Length; x++) Console.WriteLine("Arg: {0}", args[x]); Console.WriteLine("Hello World"); return 0; } }

Neste programa usamos a propriedade Length do tipo System.Array (como veremos adiante todos os arrays C# so alias do tipo System.Array) para determinar se foram passado argumentos na linha de comando. Se tiver sido passado pelo menos um argumento, o programa itera sobre cada item e faz output do contedo do array. Como alternativa, podemos iterar sobre o array de strings usando a construo C# foreach:

Autor: Andrew Troelsen Traduo: Carlos Martins

C# and the .NET Platform, 2. C# Language Fundamentals

5 de 96

A Anatomy of a Basic C# Class (5)


// Notice we have no need to check the size of the array when using "foreach". public static int Main(string[] args) { foreach (string s in args) Console.WriteLine("Arg: {0}", s); Console.WriteLine("Hello World"); return 0; }

O programador o nico responsvel por determinar quais os parmetros da linha de comando a que a aplicao dever responder, e o que deve fazer com cada parmetro.

Autor: Andrew Troelsen Traduo: Carlos Martins

C# and the .NET Platform, 2. C# Language Fundamentals

6 de 96

Creating Objects: Constructor Basics (1)


As linguagens que suportam a programao orientada por objectos distinguem de forma clara classes e objectos. Uma classe uma definio de um tipo user-defined (UDT), sendo considerada o projecto (planta) para todas as variveis desse tipo. Objecto o termo que descreve a instncia de uma classe particular. Em C#, a palavra chave new a nica forma de criar uma instncia de uma classe. Para exemplificar, observe a seguinte actualizao do mtodo Main.
// Make some HelloClass objects when the static Main() method is called. using System; class HelloClass { public static int Main(string[] args) { // You can declare and create an object in a single line HelloClass c1 = new HelloClass(); // ... or, break the declaration into two lines HelloClass c2; c2 = new HelloClass(); return 0; } }

A palavra chave new tem a responsabilidade de reservar o nmero de bytes necessrio para o objecto especificado, e adquirir memria necessria no managed heap. No exemplo, reservmos dois objectos (c1 e c2) cada um dos quais aponta para uma instncia do tipo HelloClass. Tenha em ateno que as variveis classe C# so na realidade uma referncia para o objecto em memria, no o prprio objecto. C# and the .NET Platform, 2. C# Language Fundamentals

Autor: Andrew Troelsen Traduo: Carlos Martins

7 de 96

Creating Objects: Constructor Basics (2)


Assim, c1 e c2 so referncias para objectos distintos do tipo HelloClass alojados no managed heap (no Captulo 3 so explicados os detalhes). O cdigo anterior invoca o construtor por omisso da classe. Todas as classes C# so dotadas automaticamente de construtor por omisso, que poder ser redefinido sempre que necessrio. Tal como no C++, o construtor por omisso no tem parmetros. Para alm de criar uma nova instncia do objecto, o construtor por omisso assegura que todas as variveis membro da classe so iniciadas com os valores por omisso adequados (esta afirmao verdadeira para todos os construtores). Tipicamente, as classes especficas definem construtores adicionais, para alm do construtor por omisso. Desta forma fornecemos ao utilizador do objecto uma forma simples de iniciar o respectivo estado, no momento da sua criao. A seguir apresentase, de novo, o tipo HelloClass com um construtor especfico, construtor por omisso redefinido e informao de estado:
// Helloclass with constructors using System; class HelloClass { // The default constructor always assign state data to default values public HelloClass() { Console.WriteLine("Default ctor called!"); }

Autor: Andrew Troelsen Traduo: Carlos Martins

C# and the .NET Platform, 2. C# Language Fundamentals

8 de 96

Creating Objects: Constructor Basics (3)


// This custom constructor assigns state data to a known value. public HelloClass(int x, int y) { Console.WriteLine("Custom ctor called!"); intX = x; intY = y; } // Some public state data public int intX, intY; // Program entry point. public static int Main(string[] args) { // Trigger default constructor. HelloClass c1 = new HelloClass(); Console.WriteLine("c1.intX = {0}\nc1.intY = {1}\n", c1.intX, c1.intY); // Trigger parameterized constructor. HelloClass c2 = new HelloClass(100, 200); Console.WriteLine("c2.intX = {0}\nc2.intY = {1}\n", c2.intX, c2.intY); return 0; } }

Examinando o output do programa podemos ver que o construtor por omisso inicia a informao de estado com os valores por omisso (zero), enquanto que o construtor especfico inicia os membros dados com os valores especificados pelo utilizador.

Autor: Andrew Troelsen Traduo: Carlos Martins

C# and the .NET Platform, 2. C# Language Fundamentals

9 de 96

Creating Objects: Constructor Basics (4)


That a Memory Leak?
Repare que o mtodo Main no tem lgica para destruir explicitamente as instncias c1 e c2:
// Leaky method? public static int Main(string[] args) { HelloClass c1 = new HelloClass(); Console.WriteLine("c1.intX = {0}\nc1.intY = {1}\n", c1.intX, c1.intY); HelloClass c2; c2 = new HelloClass(100, 200); Console.WriteLine("c2.intX = {0}\nc2.intY = {1}\n", c2.intX, c2.intY); // Hey! Did someone forget to delete these objects? return 0; }

No se trata de uma omisso grave, mas sim da forma do .NET fazer as coisas. Tal como os programadores de Visual Basic e de Java, os programadores de C# no tm que fazer a destruio explcita dos objectos. O garbage collector do .NET libertar automaticamente a memria, razo pela qual o C# no usa a palavra chave delete.

Autor: Andrew Troelsen Traduo: Carlos Martins

C# and the .NET Platform, 2. C# Language Fundamentals

10 de 96

The Composition of a C# Application (1)


O tipo HelloClass corrente foi definido para realizar duas funes:definir o entry point para a aplicao e manter dois membros dados iniciados nos construtores. Embora isto seja correcto, pode parecer estranho que o mtodo esttico Main() crie uma instncia da classe onde se encontra definido.
class HelloClass { public HelloClass() { Console.WriteLine("Default ctor called"); } public HelloClass(int x, int y) { Console.WriteLine("Custom ctor called"); } public int intX, intY; public static int Main(string[] args) { // Make some HelloClass objects... HelloClass c1 = new HelloClass(); ... } }

Muitos dos nossos exemplo iniciais seguem este padro, porque o nosso objectivo manter o foco no tpico em discusso. No entanto, seria mais natural dividir a classe HelloClass em duas classes distintas: HelloClass e HelloApp. Usando a terminologia da programao orientada por objectos, este diviso designa-se separao de funes. Assim, podemos rescrever a aplicao do seguinte modo:

Autor: Andrew Troelsen Traduo: Carlos Martins

C# and the .NET Platform, 2. C# Language Fundamentals

11 de 96

The Composition of a C# Application (2)


class HelloClass { public HelloClass() { Console.WriteLine("Default ctor called"); } public HelloClass(int x, int y) { Console.WriteLine("Custom ctor called"); intX = x; intY = y; } public int intX, intY; // Member function public void SayHi() { Console.WriteLine("Hi there!"); } } class HelloApp { public static int Main(string[] args) { // Make some HelloClass objects and say howdy. HelloClass c1 = new HelloClass(); c1.SayHi() ... } }

Quando se constrem aplicaes, comum definir um tipo que funciona como objecto aplicao (o tipo que define o mtodo Main) e outros tipos que constituem a prpria aplicao. Ainda, para manter o cdigo manejvel, cada tipo colocado num ficheiro *.cs prprio.

Autor: Andrew Troelsen Traduo: Carlos Martins

C# and the .NET Platform, 2. C# Language Fundamentals

12 de 96

The Composition of a C# Application (3)


Member Initialization
Como cada classe pode definir vrios construtores, podemos ser colocados perante a tarefa aborrecida de ter que escrever vrias vezes o mesmo cdigo de iniciao. Isso particularmente necessrio quando no pretendemos aceitar os valores por omisso das membros dados. Para evitar esta redundncia, o C# permite afectar valores iniciais aos membros dados no momento da sua declarao:
// This technique is useful when you dont want to accept default values and // would rather not write the same initialization code in each constructor. class Test { private int myInt = 90; private string myStr = "My initial value"; private HotRod viper = new HotRod(200, "Chucky", Color.Red); ...

Outras linguagens que suportam a programao orientada por objectos, como o C++, no permitem esta forma de iniciao dos membros. Nesse caso, os programadores podem optar por escrever funes auxiliares privadas que so chamadas nos construtores. Outra soluo ser encaminhar as chamadas a um construtor para um outro que funcione como master (analisaremos esta tcnica no Captulo 3 durante a discusso da palavra chave this). Embora qualquer uma daquelas construes seja tambm vlida em C#, a iniciao explcita dos membros dados mais uma alternativa.

Autor: Andrew Troelsen Traduo: Carlos Martins

C# and the .NET Platform, 2. C# Language Fundamentals

13 de 96

The Composition of a C# Application (4)


Basic Input and Output with the Console Class
No tipo HelloClass escrito anteriormente utilizmos a classe System.Console, definido no namespace System. Como o nome sugere, esta classe encapsula a manipulao dos streams input, output e error. Os mtodos principais de Console so ReadLine e WriteLine, ambos definidos como estticos. O mtodo WriteLine escreve um string (seguido de carriage return) no stream output. O mtodo Write escreve texto no stream output, mas no inclui o carriage return. O mtodo ReadLine permite recolher informao do stream input at um carriage return, enquanto que o mtodo Read pode ser usado para ler um caracter do stream input. Para ilustrar o I/O bsico usando a classe Console, considere o seguinte programa:
// Make use of the Console class to perform basic IO. using System; class BasicIO { public static Main(string[] args) { Console.Write("Enter your name: "); string s = Console.ReadLine(); Console.WriteLine("Hello, {0}", s); Console.Write("Enter your age: "); s = Console.ReadLine(); Console.WriteLine(" You are {0} years old\n", s); } }

Autor: Andrew Troelsen Traduo: Carlos Martins

C# and the .NET Platform, 2. C# Language Fundamentals

14 de 96

The Composition of a C# Application (5)


Introducing C# String Formatting
Durante estes primeiros exemplos, temos visto muitas vezes os tokens {0} e {1}. O .NET introduz um novo estilo de formatao de strings, com algumas reminiscncias na funo printf da linguagem C. Por exemplo:
using System; class BasicIO { public static Main() { ... int theInt = 90; float theFloat = 9.99; BasicIO myIO = new BasicIO(); // Format a string... Console.WriteLine("Int is: {0}\nFloat is: {1}\nYou are: {2}", theInt, theFloat, myIO.ToString()); } }

O primeiro parmetro de WriteLine representa o string de formatao que contm placeholders opcionais designados por {0}, {1}, {2}, e assim sucessivamente. Os restantes parmetros de WriteLine so os valores que pretendemos ver inseridos no respectivo placeholder (neste caso, um inteiro, um float e um string). Tenha tambm em considerao que o mtodo WriteLine tem uma definio que permite especificar os valores a atribuir aos placeholders como array de objectos. Assim, podemos representar qualquer numero de itens, do seguinte modo: C# and the .NET Platform, 2. C# Language Fundamentals
15 de 96

Autor: Andrew Troelsen Traduo: Carlos Martins

The Composition of a C# Application (6)


// Fill placeholders using an array of objects. object[] stuff = {"Hello", 20.9, 1, "There", "83", 99.99933 }; Console.WriteLine("The Stuff: {0}, {1}, {2}, {3}, {4}, {5}", stuff);

Cada placeholder poder conter vrios caracteres de formatao, como se mostra na Tabela 2-1. Estes caracteres de formatao so colocados dentro dos placeholders usando o caracter : como separador (por exemplo, {0:C}, {1:d}, {2:X}, e assim sucessivamente). Para ilustrar, analise o seguinte cdigo:
// Now make use of some format tags. public static void Main() { ... Console.WriteLine("C format: {0:C}", 99989.987); Console.WriteLine("D9 format: {0:D9}", 99999); Console.WriteLine("E format: {0:E}", 99999.76543); Console.WriteLine("F format: {0:F3}", 99999.9999); Console.WriteLine("N format: {0:N}", 99999); Console.WriteLine("X format: {0:X}", 99999); Console.WriteLine("x format: {0:x}", 99999); }

Autor: Andrew Troelsen Traduo: Carlos Martins

C# and the .NET Platform, 2. C# Language Fundamentals

16 de 96

The Composition of a C# Application (7)


Table 2-1. C# Format Characters
C# Format Character C or c D or d E or e F or f G or g N or n X or x Meaning in Life Used to format currency. By default, the flag will prefix a dollar sign ($) to the value, however this can be changed using a NumberFormatInfo object. Formats decimal numbers. This flag my also specify the minimum number of digits used to pad the value. Exponential notation. Fixed point formatting. General. Used to format a number to fixed or exponential format. Basic numerical formatting (with commas). Hexadecimal formatting. If you use an uppercase X, your hex format will also contain uppercase characters.

Autor: Andrew Troelsen Traduo: Carlos Martins

C# and the .NET Platform, 2. C# Language Fundamentals

17 de 96

The Composition of a C# Application (8)


A utilizao dos caracteres de formatao do C# no se limita ao mtodo System.Console.WriteLine. Por exemplo, podem ser usadas estas mesmas flags com o mtodo esttico String.Format. Este mtodo torna-se til quando necessrio construir um string em memria contendo valores numricos.
// Use the static String.Format() method to build a new string. string formStr; formStr = String.Format("Don't you wish you had {0:C} in your account", 99989.987); Console.WriteLine(formStr);

Autor: Andrew Troelsen Traduo: Carlos Martins

C# and the .NET Platform, 2. C# Language Fundamentals

18 de 96

Understanding Value Types and Reference Types (1)


Tal como as outras linguagens de programao, o C# define um conjunto de tipos de dados intrnsecos. Existem tipos para representar nmeros inteiros, strings, nmeros em vrgula flutuante, etc.. Quando cria uma varivel com o tipo inteiro (int), todas as linguagens .NET conhecem esse tipo e operam sobre a mesma gama de valores. Um tipo C# pode ser value-based ou reference-based. Os tipos value-based, onde se integram todos os tipos numricos, as enumeraes e as estruturas, so alojados no stack ou no managed heap quando so campos de tipos reference-based. Quando se afecta um tipo valor com outro tipo valor, realizada a cpia bit a bit. Para ilustrar, assuma que temos a seguinte estrutura C# e a seguinte lgica no mtodo Main:
// Structures are value types. struct FOO { public int x, y; } class ValueRefClass { // Exercise some value types. public static void Main() { // The 'new' keyword is optional when creating structures using the // default ctor. FOO f1 = new FOO(); f1.x = 100; f1.y = 100; // Assign a new FOO type (f2) to an existing FOO type (f2). FOO f2 = f1; // Here is f1... Console.WriteLine("f1.x = {0}\nf1.y = {1}", f1.x, f1.y);

Autor: Andrew Troelsen Traduo: Carlos Martins

C# and the .NET Platform, 2. C# Language Fundamentals

19 de 96

Understanding Value Types and Reference Types (2)


// Here is f2... Console.WriteLine("f2.x = {0}\nf2.y = {1}", f2.x, f2.y); // Change f2.x. This will NOT change f1.x. Console.WriteLine("Changing f2.x"); f2.x = 900; // Print again Console.WriteLine("f2.x = {0}\nf1.x = {1}", f2.x, f1.x); } }

Foi criada uma varivel do tipo FOO (f1) que foi depois atribuda a outra varivel do tipo FOO (f2). Uma vez que FOO um tipo valor, ficamos com duas cpias do tipo FOO no stack, que podem ser manipuladas de forma independente. Por isso, quando se altera o valor de f2.x, o valor de f1.x no alterado. Os tipos referncia (que incluem as classes e as interfaces) so alojadas no managed heap. As cpias de tipos referncia so cpias superficiais, tendo por consequncia que mltiplas referncias fiquem a apontar a mesma localizao na memria. Para ilustrar altere a definio do tipo FOO de uma estrutura C# para uma classe:
class FOO { // Classes are always reference types. public int x, y; }

Autor: Andrew Troelsen Traduo: Carlos Martins

C# and the .NET Platform, 2. C# Language Fundamentals

20 de 96

Understanding Value Types and Reference Types (3)


Executando de novo o programa anterior, verifique que o comportamento diferente. Agora, temos dois objectos a referenciar a mesma zona de memria no managed heap. Por isso, quando se altera o valor de x usando f2, f1 reflecte essa alterao. Para compreender melhor a distino entre tipos valor e tipos referncia, consulte a Tabela 2-2 que responde a um certo nmero de questes intrigantes (muitas das quais sero examinadas em detalhe ao longo deste texto).
Table 2-2. Value Types and Reference Types Side by Side
Intriguing Question Where is this type allocated? How is a variable represented? What is the base type? Value Type Allocated on the stack Value type variables are local copies Most directly derive from System.ValueType Reference Type Allocated on the managed heap Reference type variables are pointing to the memory occupied by the allocated instance. Can derive from any other type (except System.ValueType) as long as that type is not "sealed"... more later

Value and Reference Types: Further Details

Autor: Andrew Troelsen Traduo: Carlos Martins

C# and the .NET Platform, 2. C# Language Fundamentals

21 de 96

Understanding Value Types and Reference Types (4)


Table 2-2. Value Types and Reference Types Side by Side (continued) Intriguing Question Can this type function as a base to other types? What is the parameter passing behavior? Value Type No. Value types are always sealed and cannot be extended Variables are passed by value (i.e., a copy of the variable is passed into the called function) No. Value types are never placed onto the heap and therefore do not need to be finalized Yes,but the default constructor is reserved (i.e. your custom constructors must all have arguments) When it falls out of the defining scope Reference Type Yes. If the type is not sealed, it may function as a base to other types Variables are passed by reference (e.g., address of the variable is passed into the called function) Yes... indirectly (more details in Chapter 3) But, of course!

Able to override Object.Finalize()? Can I define constructors for this type?

When do variables for this type die?

When the managed heap is garbage collected

Autor: Andrew Troelsen Traduo: Carlos Martins

C# and the .NET Platform, 2. C# Language Fundamentals

22 de 96

Understanding Value Types and Reference Types (5)


Apesar das suas diferenas, os tipos valor e os tipos referncia tm ambos a capacidade de implementar interfaces standard e interfaces especficas, e podem suportar qualquer nmero de campos, mtodos, propriedades e eventos. Para consolidar algumas das diferenas mais importantes entre tipos valor e tipos referncia, considere o seguinte cdigo:
// A value type. struct PERSON { public string Name; public int age; } // A reference type. class Person { public string Name; public int age; } class ValRefClass { public static void Main() { // Create an object reference on the managed heap. Person fred = new Person(); // Create a value on the stack. PERSON mary = new PERSON(); // This performs a bit copy, resulting in two structures on the stack. PERSON jane = mary; // This performs a shallow copy, resulting in two references to the same // object in memory. Person fredRef = fred; } }

Autor: Andrew Troelsen Traduo: Carlos Martins

C# and the .NET Platform, 2. C# Language Fundamentals

23 de 96

The Master Node: System.Object (1)


Em C#, cada tipo de dados (valor ou referncia) deriva de um classe base comum: System.Object. Esta classe define comportamento polimrfico comum a todos os tipos do universo .NET. Nas definies do tipo HelloClass que fizemos anteriormente, no indicmos explicitamente Object como classe base, mas essa derivao assumida pelo compilador. Se pretender explicitar System.Object como classe base, pode definir as suas classes de acordo com o seguinte padro:
// Here we are explicitly deriving from System.Object. // We could also write: "Class HelloCLass : object". class HelloClass : System.Object {...}

Como qualquer outra classe C#, System.Object define um conjunto de membros de instncia. Repare que alguns desses itens so declarados virtual e podem, por isso, ser sobrepostos pelas subclasses:
// The top-most class in the .NET world: System.Object. namespace System { public class Object { public Object(); public virtual Boolean Equals(Object obj); public virtual Int32 GetHashCode(); public Type GetType(); public virtual String ToString(); protected virtual void Finalize(); protected Object MemberwiseClone(); ... } ... }

Autor: Andrew Troelsen Traduo: Carlos Martins

C# and the .NET Platform, 2. C# Language Fundamentals

24 de 96

The Master Node: System.Object (2)


A Tabela 2-3 apresenta um resumo da funcionalidade de cada mtodo. Para ilustrar algum do comportamento por omisso oferecido pela classe base Object, considere as seguintes definies de classes:
// Create some objects and exercise the inherited System.Object methods. using System; class ObjTest { public static int Main(string[] args) { // Make an instance of ObjTest. ObjTest c1 = new ObjTest(); // Pump info to console. Console.WriteLine("ToString: {0}", c1.ToString()); Console.WriteLine("Hash code: {0}", c1.GetHashCode()); Console.WriteLine("Type: {0}", c1.GetType().ToString()); // Make some other references to c1. ObjTest c2 = c1; Object o = c2; // Are all 3 instances pointing to the same object in memory? if (o.Equals(c1) && c2.Equals(o)) Console.WriteLine("Same instance!"); return 0; } }

Primeiro, repare que a implementao por omisso de ToString devolve simplesmente o nome do tipo (ObjTest). Em muitas situaes, as classes derivadas redefinem este mtodo para devolver um string que represente os valores dos seus dados internos. C# and the .NET Platform, 2. C# Language Fundamentals

Autor: Andrew Troelsen Traduo: Carlos Martins

25 de 96

The Master Node: System.Object (3)


Table 2-3. Core Members of System.Object Instance Method of Object Class Equals

Meaning in Life
By default this method returns true only if the items being compared refer to the same exact item in memory. Thus, Equals() is used to compare object references, not the state of the object. Typically, this method is overridden to return "true" only if the objects being compared have the same internal state values (that is, value-based semantics). Be aware that if you override Equals(), you should also override GetHashCode(). Returns an integer that identifies a specific object instance. This method returns a Type object that fully describes the object you are currently referencing. In short, this is a Runtime Type Identification (RTTI) method available to all objects (discussed in greater detail in Chapter 7). Returns a string representation of this object, using the <namespace>.<class name> format (termed the "fully qualified name"). If the type has not been defined within a namespace <class name> is returned. For the time being, you can understand this method (when overridden) is called to free any allocated resources before the object is destroyed. We talk more about the CLR garbage collector services in Chapter 3.

GetHashCode GetType

ToString

Finalize

Autor: Andrew Troelsen Traduo: Carlos Martins

C# and the .NET Platform, 2. C# Language Fundamentals

26 de 96

The Master Node: System.Object (4)


Table 2-3. Core Members of System.Object (continued) Instance Method of Object Class MemberwiseClone Meaning in Life This protected method exists to return a member by member copy of the object. Reference fields are also copied from the old object to the new, but this means that the reference fields in the new object point to the same objects as those in the old object. This is the definition of "shallow copy". As you will see in the Chapter 4, this method is helpful when building types which implement the ICloneable interface.

Analisemos agora o seguinte bloco de cdigo:


// Compare object references. public static int Main() { // Make an instance of ObjTest. ObjTest c1 = new ObjTest(); ... // Make some other references to c1. ObjTest c2 = c1; Object o = c2; // Are all 3 instances pointing to the same object in memory? if (o.Equals(c1) && c2.Equals(o)) Console.WriteLine("Same instance!"); return 0; }

Autor: Andrew Troelsen Traduo: Carlos Martins

C# and the .NET Platform, 2. C# Language Fundamentals

27 de 96

The Master Node: System.Object (5)


O comportamento por omisso do mtodo Equals() comparar os objectos usando semntica de referncia e no semntica de valor. Neste exemplo, crimos uma nova varivel do tipo ObjTest designada c1, que tem como consequncia o alojamento de um novo objecto ObjTest no managed heap. c2 tambm do tipo ObjTest. Contudo, no crimos uma nova instncia, mas apenas atribumos esta varivel referncia c1. Em consequncia, c1 e c2 apontam o mesmo objecto em memria ( assim como a varivel o), pelo que o teste pela igualdade tem sucesso. Embora o comportamento pr-definido em Object possa servir em muitas situaes, comum que os tipos especficos redefinam alguns mtodos. Por exemplo, assuma que rescrevemos a classe Person por forma a acrescentar informao de estado para armazenar o nome, o nmero da segurana social e a idade:
// Remember! All classes implicitly derive from Object. class Person { public Person(string fname, string lname, string ssn, byte a) { firstName = fname; lastName = lname; SSN = ssn; age = a; } public Person() {} // All member variables assigned to default values.

Override Some Default Behaviors of System.Object

Autor: Andrew Troelsen Traduo: Carlos Martins

C# and the .NET Platform, 2. C# Language Fundamentals

28 de 96

The Master Node: System.Object (6)


// The public public public public } state of a person string firstName; string lastName; string SSN; byte age;

Para comear, vamos redefinir o mtodo Object.ToString para devolver uma representao textual do estado do objecto. Examinaremos os detalhes da redefinio de mtodos no prximo captulo. Por agora, considere apenas que estamos a alterar o comportamento do mtodo ToString para a classe Person.
// Need to reference this namespace to access the StringBuilder type. using System.Text; // A Person class implements ToString() as so: class Person { ... // Overriding a method inherited from System.Object. public override string ToString() { StringBuilder sb = new StringBuilder(); sb.Append("[First Name = " + this.firstName); sb.Append(" LastName = " + this.lastName); sb.Append(" SSN = " + this.SSN); sb.Append(" Age = " + this.age + "]"); return sb.ToString(); } ... }

Autor: Andrew Troelsen Traduo: Carlos Martins

C# and the .NET Platform, 2. C# Language Fundamentals

29 de 96

The Master Node: System.Object (7)


O formato do string devolvido pelo mtodo ToString para um dado tipo uma questo de gosto pessoal. Neste exemplo, optmos por incluir nesse string pares nome/valor entre parntesis rectos. (Repare que neste exemplo utilizamos um novo tipo, System.Text.StringBuilder. Este tipo ser descrito em detalhe mais frente neste captulo.) Vamos agora redefinir o mtodo Object.Equals para ter uma semntica baseada no valor. Recorde que, por omisso, este mtodo devolve apenas true se as dois objectos que esto a ser comparados se referem mesma instncia na memria. Na classe Person, seria til implementar Equals por forma a devolver true se as duas variveis comparadas tiverem os mesmos valores nas suas variveis de estado (e.g., nome, nmero da segurana social e idade):
// A Person class implements Equals() as so: class Person { ... public override bool Equals(Object o) { // Does the incoming Person have the same values as me? Person tmp = (Person)o; return tmp.firstName == this.firstName && tmp.lastName == this.lastName && tmp.SSN == this.SSN && tmp.age == this.age; } }

Autor: Andrew Troelsen Traduo: Carlos Martins

C# and the .NET Platform, 2. C# Language Fundamentals

30 de 96

The Master Node: System.Object (8)


Antes de testarmos o comportamento do tipo Person, temos que ter em ateno mais um detalhe. Quando uma classe redefine o mtodo Equals, dever tambm ser redefinido o mtodo GetHashCode (quando isso no feito, o compilador emite um aviso). Este mtodo devolve o valor numrico usado para identificar o objecto em memria, que frequentemente utilizado pela implementao das coleces baseadas em tabelas de hash. Existem muitos algoritmos que podem ser utilizados para criar um cdigo de hash, alguns imaginativos, outros nem tanto. Para os propsitos do nosso exemplo, vamos assumir que o cdigo de hash do string que representa o SSN um valor razovel:
// Return a hash code based on the person's SSN. public override int GetHashCode() { return SSN.GetHashCode(); }

Vamos agora testar a classe Person:


// Make a few people and play with the overridden Object methods. public static int Main() { // Now make some people and test for equality. // NOTE: We want these to be identical to test Equals() method. Person p1 = new Person("Fred", "Jones", "222-22-2222", 98); Person p2 = new Person("Fred", "Jones", "222-22-2222", 98); // Equals() now uses value semantics (same hash codes). if (p1.Equals(p2) && p1.GetHashCode() == p2.GetHashCode()) Console.WriteLine("P1 and P2 have same state\n"); else Console.WriteLine("P1 and P2 are DIFFERENT\n");

Autor: Andrew Troelsen Traduo: Carlos Martins

C# and the .NET Platform, 2. C# Language Fundamentals

31 de 96

The Master Node: System.Object (9)


// Change the state of p2. p2.age = 2; // Test again (same hash codes). if (p1.Equals(p2) && p1.GetHashCode() == p2.GetHashCode()) Console.WriteLine("P1 and P2 have same state\n"); else Console.WriteLine("P1 and P2 are DIFFERENT\n"); // Get 'stringified' version of objects. Console.WriteLine(p1.ToString()); Console.WriteLine(p2); // ToString() called automatically return 0; }

Static Members of System.Object Alm dos membros de instncia que acabmos de analisar, a classe System.Object define
dois membros estticos (Object.Equals e Object.ReferenceEquals)que testam tambm a igualdade com semntica de valor e com semntica de referncia. Considere o seguinte cdigo:
// Static members of System.Object. Person p3 = new Person("Sally", "Jones", "333", 4); Person p4 = new Person("Sally", "Jones", "333", 4); // Do P3 and P4 have the same state? TRUE! Console.WriteLine("P3 and P4 have same state: {0}", object. Equals(p3, p4)); // Are they the same object in memory? FALSE! Console.WriteLine("P3 and P4 are pointing to the same object: {0}", object.ReferenceEquals(p3, p4));

Autor: Andrew Troelsen Traduo: Carlos Martins

C# and the .NET Platform, 2. C# Language Fundamentals

32 de 96

The System Data Types (and C# Aliases) (1)


Cada tipo intrnseco C# , na realidade, um sinnimo dos tipos definidos no namespace System. A Tabela 2-4 enumera os tipos do sistema, a respectiva gama de valores, o tipo C# correspondente e a respectiva compatibilidade com a Common Language Specification (CLS).
Table 2-4. System Types and C# Aliases C# Alias sbyte byte short ushort CLS Compliant? No Yes Yes No System Type SByte Byte Int16 UInt16 Range -128 to +127 0 to 255 -32,768 to +32,767 0 to 65535 Meaning in Life Signed 8-bit number Unsigned 8-bit number Signed 16-bit number Unsigned 16-bit number

int
uint long

Yes
No Yes

Int32
UInt32 Int64

-2,147,483,648 to +2,147,483,647
0 to 4,294,967,295 -9,223,372,036,854,775,808 to +9,223,372,036,854,775,807

Signed 32-bit number


Unsigned 32-bit number Signed 64-bit number

Autor: Andrew Troelsen Traduo: Carlos Martins

C# and the .NET Platform, 2. C# Language Fundamentals

33 de 96

The System Data Types (and C# Aliases) (2)


Table 2-4. System Types and C# Aliases (continued) C# Alias CLS Compliant? System Type Range Meaning in Life

ulong
char float double bool decimal string object

No
Yes Yes Yes Yes Yes Yes Yes

UInt64
Char Single Double Boolean Decimal String Object

0 to 18,446,744,073,709,551,615
U+0000 to U+ffff 1.5x10-45 to 3.4x1038 5.0x10-324 to 1.7x10308 true or false ((-296 to 296)/ 10 (0 to 28)) Limited by system memory Anything at all. All classes derive from object. Therefore, everything is an object.

Unsigned 64-bit number.


A single 16-bit Unicode character. 32-bit floating pointer number. 64-bit floating pointer number. Represents truth or falsity. A 96-bit signed number Represents a set of Unicode characters. The base class of all types in the .NET universe.

Autor: Andrew Troelsen Traduo: Carlos Martins

C# and the .NET Platform, 2. C# Language Fundamentals

34 de 96

The System Data Types (and C# Aliases) (3)


A relao entre os tipos fundamentais do sistema (assim como outros tipos que discutiremos a seguir) mostrada na Figura 2-10. A figura mostra que, em ltima anlise, cada um dos tipos deriva de System.Object. Uma vez que um tipo como int uma mera abreviatura do tipo correspondentes do sistema, Int32, podemos usar a seguinte sintaxe:
// Remember! A C# int is really an alias for System.Int32. Console.WriteLine(12.ToString());

Repare tambm, que nem todos os tipos suportados pelo C# so compatveis com as regras do CLS. Quando se criam tipos especficos para funcionar de forma transparente em todas as linguagens, apenas se devem usar os tipos compatveis CLS. A maioria dos tipos de dados intrnsecos do C# correspondem a uma estrutura derivada de System.ValueType. O tipo System.ValueType existe para redefinir, com semntica baseada em valor, os mtodos virtuais definidos por System.Object. Na realidade, as assinaturas dos mtodos definidos por ValueType so iguais s definidas por Object. No entanto, tenha em considerao que quando so comparadas duas instncias, estamos a utilizar uma semntica baseada no valor:

Experimenting with the System Type Classes

Autor: Andrew Troelsen Traduo: Carlos Martins

C# and the .NET Platform, 2. C# Language Fundamentals

35 de 96

The System Data Types (and C# Aliases) (4)


Boolean Object Byte UInt32 Char UInt64 ValueType Any type that derives from ValueType is a structure not a class. Decimal Void Double DateTime Int16 Guid Int32 TimeSpan Int64 Single SByte UInt16 Type String Array Exception Delegate

MultiCastDelegate

Figure 2-10. The hierarchy of System Types


Autor: Andrew Troelsen Traduo: Carlos Martins

Enum

C# and the .NET Platform, 2. C# Language Fundamentals

36 de 96

The System Data Types (and C# Aliases) (5)


// Test value semantics. System.Int32 intA = 1000; // Same as: int intA = 1000; System.Int32 intB = 1000; // Same as: int intB = 1000; // The test succeeds! The two instances contain the same value. if (intA == intB) Console.WriteLine("Same value!");

Todos os tipos derivados de System.ValueType (e.g., Int32, Char, Boolean, etc.) tm alguns membros utilitrios semelhantes. Por exemplo, as propriedades MaxValue e MinValue permitem determinar o valor mximo e o valor mnimo que cada tipo pode armazenar. Assuma que criou uma varivel do tipo System.UInt16, e que a utiliza do seguinte modo:
// Note que an implicit data type (ushort) has the same methods available // as the corresponding wrapper (System.Uint16). class MyDataTypes { public static void Main() { // Working with UInt16 as a structure. System.UInt16 myUInt16 = 30000; Console.WriteLine("Max for an UInt16 is: {0}", UInt16.MaxValue); Console.WriteLine("Min for an UInt16 is: {0}", UInt16.MinValue); Console.WriteLine("I am a: {0}", myUInt16.GetType().ToString()); // Now in UInt16 shorthand (e.g., a ushort). ushort myOtherUInt16 = 12000; Console.WriteLine("\nYour value is: {0}", myOtherUInt16.ToString()); Console.WriteLine("I am a: {0}", myOtherUInt16.GetType().ToString()); } }

Autor: Andrew Troelsen Traduo: Carlos Martins

C# and the .NET Platform, 2. C# Language Fundamentals

37 de 96

The System Data Types (and C# Aliases) (5)


Minor Commentary on Select Data Types
Alguns tipos do sistema merecem comentrios especiais. O primeiro, o tipo System.Boolean. Ao contrrio do C(++), apenas este tipo apenas pode ser afectado com os valores {true | false} :
// No more ad hoc Boolean types in C# bool b = 0; // Illegal! bool b2 = -1; // Also Illegal! bool b3 = true; // No problem. bool b4 = false; // No problem.

importante tambm realar que em C# a representao de texto usa os tipos string e char. Desaparecem finalmente os tipos char*, wchar_t*, LPSTR, LPCSTR, BSTR e OLECHAR. Todos estamos de acordo que a manipulao de texto em COM e Win32 horrvel. O C# oferece uma forma simplificada de manipulao de strings, na medida em que todas as linguagens .NET usam os tipos System.String e System.Char que representam o texto com caracteres Unicode.

Autor: Andrew Troelsen Traduo: Carlos Martins

C# and the .NET Platform, 2. C# Language Fundamentals

38 de 96

Moving Between Value Types and Reference Types: Boxing and Unboxing (1)
O C# providencia um mecanismo para fazer a converso entre tipos referncia e tipos valor, designado por boxing. Assuma que crimos um tipo valor simples:
// Make a simple value data point. short s = 25;

Se, durante o curso da sua aplicao, for necessrio converter este tipo valor para a referncia para objecto correspondente, deve fazer box do valor do seguinte modo:
// Box the value into an object reference. object objShort = s;

O boxing pode ser definido como o processo de converter explicitamente um tipo valor no tipo referncia correspondente. Quando se faz box de um valor, o que estamos essencialmente a fazer reservar um novo objecto no managed heap e a copiar o valor interno (25) para esse objecto. A operao inversa tambm permitida e designa-se unboxing. Unboxing o termo dado ao processo de converter uma referncia para um objecto para o tipo valor correspondente. A operao unboxing comea por verificar se o tipo de dados receptor equivalente ao tipo boxed e, em caso afirmativo, copia o valor. Por exemplo, a seguinte operao de unboxing correcta, dado que o tipo subjacente a objShort short:
// Now, unbox the reference back into a corresponding short. short anotherShort = (short)objShort;

Autor: Andrew Troelsen Traduo: Carlos Martins

C# and the .NET Platform, 2. C# Language Fundamentals

39 de 96

Moving Between Value Types and Reference Types: Boxing and Unboxing (2)
Contudo, a seguinte operao de unboxing gera uma excepo InvalidCastException:
// Bad unboxing! public static int Main() { ... try { // The type contained in the box is NOT a string, but a short! string str = (string)objShort; } catch (InvalidCastException e) { Console.WriteLine("OOPS!\n{0}", e.ToString()); } ... }

Poder perguntar em que circunstncias ser necessrio fazer box (ou unbox) de um tipo? A resposta quase nunca. Na realidade, na maior parte das circunstncias o compilador de C# faz box e unbox quando necessrio. Por exemplo, se passar um tipo valor para um mtodo que receba como parmetro um objecto, ocorre uma operao de boxing:
// Assume the following method: public void Foo(object o) int x = 99; Foo(x); // Automatic boxing.

Por vezes o boxing e unboxing poder ser usado explicitamente para melhorar o desempenho das aplicaes. Voltaremos ao boxing adiante neste captulo aquando da discusso formal das estruturas C#. C# and the .NET Platform, 2. C# Language Fundamentals
40 de 96

Autor: Andrew Troelsen Traduo: Carlos Martins

Default Assignments and Variable Scope (1)


J afirmmos neste captulo que todos os tipos de dados intrnsecos do .NET tm um valor por omisso. Quando se criam tipos especficos, todas as variveis membro so automaticamente afectadas com esse valor por omisso. Para ilustrar, considere a seguinte definio de classe:
// C# automatically sets all member variables to a safe default value. class DefValObject { // Here are a number of fields public sbyte theSignedByte; public byte theByte; public short theShort; public ushort theUShort; public int theInt; public uint theUint; public long theLong; public char theChar; public float theFloat; public double theDouble; public bool theBool; public decimal theDecimal; public string theStr; public object theObject; public static int Main() { DefValObject v = new DefValObject(); return 0; // Set breakpoint here and check out the Autos window. } }

Autor: Andrew Troelsen Traduo: Carlos Martins

C# and the .NET Platform, 2. C# Language Fundamentals

41 de 96

Default Assignments and Variable Scope (2)


Os valores de iniciao por omisso dos membros dados so mostrados na Figura 2-13.

Figure 2-13. All types have a safe value.

Autor: Andrew Troelsen Traduo: Carlos Martins

C# and the .NET Platform, 2. C# Language Fundamentals

42 de 96

Default Assignments and Variable Scope (3)


O mesmo no se passa quando se criam variveis com mbito de um mtodo. Neste caso, devemos atribuir um valor inicial antes de utilizar as variveis, na medida em que as mesmas no recebem um valor por omisso. Por exemplo, o seguinte cdigo resulta num erro de compilao:
// Compiler error! Must assign localInt to an initial value before use. public static void Main() { int localInt; Console.WriteLine(localInt.ToString()); }

Resolver este problema trivial, basta fazer uma afectao inicial:


// Better. Everyone is happy. public static void Main() { int localInt = 0; Console.WriteLine(localInt.ToString()); }

Existe uma excepo obrigatoriedade de afectar inicialmente uma varivel local. Se a varivel funcionar como parmetro de sada (discutido a seguir neste captulo) no necessria a afectao inicial. Os mtodos que definem parmetros [out] assumem que as variveis que chegam aos mtodos so afectadas pelo mtodo invocado.

Autor: Andrew Troelsen Traduo: Carlos Martins

C# and the .NET Platform, 2. C# Language Fundamentals

43 de 96

Defining Program Constants (1)


Aps discutir a criao de variveis, vamos analisar o oposto lgico: as constantes. O C# suporta a palavra chave const, como o C++, para permitir a definio de tipos de dados constantes. Embora seja possvel definir constantes no mbito dos mtodos, a utilizao mais interessante de const na definio de constantes no mbito das classe. Por exemplo:
// Some const data. using System; class MyConstants { // These must be accessed at the class level. public const int myIntConst = 5; public const string myStringConst = "Im a const"; public static void Main() { // Scoped constant. const string localConst = "I am a rock, I am an island"; // Use const data (note the class level scope). Console.WriteLine("myIntConst = {0}\nmyStringConst = {1}", MyConstants.myIntConst, MyConstants.myStringConst); Console.WriteLine("Local constant: {0}", localConst); } }

Quando definir uma classe utilitria que apenas contenha membros constantes, dever definir um construtor privado por forma a que a mesma nunca possa ser instanciada.

Autor: Andrew Troelsen Traduo: Carlos Martins

C# and the .NET Platform, 2. C# Language Fundamentals

44 de 96

Defining Program Constants (2)


// Private constructors prevent the creation of a given type. class MyConstants { // Some const data. public const int myIntConst = 5; public const string myStringConst = "Im a const"; // Dont let the user make this class, as its only purpose is to // define constant values. private MyConstants() {} }

Podemos obter o mesmo resultado marcando a classe "constant only" como classe abstracta. Analisaremos a utilizao desta keyword no prximo captulo. Um exemplo da sua utilizao o seguinte:
// Abstract definition also prevents the creation of a given type. abstract class MyConstants { // Some const data. public const int myIntConst = 5; public const string myStringConst = "Im a const"; }

Em qualquer dos casos, se for tentada a criao de uma instncia de MyConstants, gerado um erro de compilao. Estas tcnicas podem ser bastante teis na medida em que o C# no permite definir constantes ao nvel global. Como nota final, retenha que, ao contrrio do C++, o C# no permite a utilizao da palavra chave const na definio dos mtodos.

Autor: Andrew Troelsen Traduo: Carlos Martins

C# and the .NET Platform, 2. C# Language Fundamentals

45 de 96

C# Iteration Constructs (1)


Em termos gerais o C# providencia quatro construes de iterao: for loop foreach/in loop while loop do/while loop Os programadores de C, C++ e Java conhecem bem as instrues for, while e do while, mas muitos desconhecem a instruo foreach. Os programadores de VB, por outro lado, esto em melhor posio para compreender as quatro instrues de iterao, na medida em que o VB j suporta a sintaxe For each. Vamos analisar rapidamente cada uma das construes. Quando necessrio iterar sobre um bloco de cdigo um nmero fixo de vezes, a instruo for a instruo adequada. No essencial, podemos definir quantas vezes o bloco de cdigo executa e ainda condies de terminao. Sem exagerar, aqui fica uma amostra desta sintaxe:
// A basic for loop. public static void Main() { // Note! 'i' is only visible within the scope of the for loop. for (int i = 0; i < 10; i++) { Console.WriteLine("Number is: {0}", i); // 'i' is not visible here. }

The for Loop

Autor: Andrew Troelsen Traduo: Carlos Martins

C# and the .NET Platform, 2. C# Language Fundamentals

46 de 96

C# Iteration Constructs (2)


Todos os truques usados C, C++ e Java so vlidos para construir estas instrues em C#. possvel criar condies de terminao complexas, construir ciclos infinitos, e utilizar as palavras chave goto, break e continue. Os programadores de VB h muito que desfrutam dos benefcios da construo For each. A instruo C# equivalente permite iterar sobre os vrios elementos de um array. A seguir apresenta-se um exemplo simples que usa foreach para percorrer um array de strings com ttulos possveis para publicaes. Aps preenchido o array, itera-se sobre o seu contedo procurando as palavras COM ou .NET, usando o mtodo String.IndexOf():
// Digging into an array using foreach. public static void Main() { string[] arrBookTitles = new string[]{"Complex Algorithms", "COM for Fearful Programmer", "Do you Remember Classic COM", "C# and .NET Platform", "COM for the Angry Enginner"}; int COM = 0, NET = 0; // Assume there are no books on COM and .NET (yet). foreach (string s in arrBookTitles) { if (-1 != s.IndiexOf("COM")) COM++; else if (-1 != s.IndexOf(".NET")) NET++; } Console.WriteLine("Found {0} COM references and {1} .NET references.", COM, NET); }

The foreach/in Loop

Autor: Andrew Troelsen Traduo: Carlos Martins

C# and the .NET Platform, 2. C# Language Fundamentals

47 de 96

C# Iteration Constructs (3)


Alm de iterar sobre arrays, possvel usar a instruo foreach para iterar sobre as coleces (standard e especficas). (No Captulo 4 sero abordados os detalhes da utilizao de coleces na instruo foreach.) A instruo for tipicamente utilizada quando se conhece partida o nmero de iteraes a executar. A instruo while til nas circunstncias em que esse conhecimento no existe. Para ilustrar um ciclo while, apresentamos um exemplo de manipulao de ficheiros em C# (os detalhes so apresentados no Captulo 11). A classe StreamReader, definida no namespace System.IO, encapsula os detalhes da leitura do ficheiro. Obtemos uma instncia do tipo StreamReader como o mtodo esttico File.OpenText(). Aps abrir o ficheiro config.win, podemos iterar sobre cada linha usando StreamReader.ReadLine():
try { // Just in case we cant find the correct file ... // Open the file named 'config.win'. StreamReader strReader = File.OpenText("C:\\config.win"); // Read the next line and dump to the console. string strLine; while (null != (strLine = strReader.ReadLine())) Console.WriteLine(strLine); strReader.Close(); // Close the file } catch (FileNotFoundException e) { Console.WriteLine(e.Message); }

The while and do/while Looping Constructs

Autor: Andrew Troelsen Traduo: Carlos Martins

C# and the .NET Platform, 2. C# Language Fundamentals

48 de 96

C# Iteration Constructs (4)


A instruo do/while usada quando necessitamos de realizar uma aco um nmero indeterminado de vezes. A diferena que os ciclos do/while garantem a execuo do bloco correspondente pelo menos uma vez.
// The do/while statement string ans; do { Console.Write("Are you done? [yes] [no] : "); ans = Console.ReadLine(); } while (ans != "yes");

Autor: Andrew Troelsen Traduo: Carlos Martins

C# and the .NET Platform, 2. C# Language Fundamentals

49 de 96

C# Control Flow Constructs (1)


O C# define duas construes simples para alterar o fluxo do programa com base em vrias contingncias. A primeira a instruo if/else. Ao contrrio do C e C++, a esta instruo apenas opera sobre expresses Booleanas, razo pela qual envolvem tipicamente a utilizao dos operadores C# enumerados na Tabela 2-5. Os programadores C e C++ devem ter em ateno que os velhos truques de testar uma condio por um valor diferente de zero no funciona em C#. Por exemplo, se pretender testar se a dimenso do string com que est a trabalhar maior do que zero, pode ser tentado a escrever:
// This is illegal, given that Length returns an int, not a bool. string thoughtOfTheDay = "You CAN teach an old dog new tricks"; if (thoughtOfTheDay.Length) { // Error // stuff... }

Uma expresso correcta ser:


// No problem. if (0 != thoughtOfTheDay.Length) { // stuff... } // Better! This resolves to {true | false}

As instrues if tambm podem envolver expresses complexas com uma sintaxe idntica do C++ e do Java. Para construir essas expresses, o C# dispe dos operadores condicionais presentes na Tabela 2-6.

Autor: Andrew Troelsen Traduo: Carlos Martins

C# and the .NET Platform, 2. C# Language Fundamentals

50 de 96

C# Control Flow Constructs (2)


Table 2-5. C# Relational and Equality Operators C# Equality/Relational Operator == != < > <= >= Example if (age == 30) if ("Foo" != myStr) if (bonus < 2000) if (bonus > 2000) if (bonus <= 2000) if (bonus >= 2000) Meaning in Life Returns true only if each expression is the same. Returns true only if each expression is different. Returns true if expression A is less than, greater than, less than or equal to, or greater than or equal to expression B

Table 2-6. C# Conditional Operators


C# Conditional Operator && || ! Example if ((age == 30) && (name == "Fred")) if ((age == 30) || (name == "Fred")) if (!myBool) Meaning in Life Conditional AND. Conditional OR. Conditional NOT..

Autor: Andrew Troelsen Traduo: Carlos Martins

C# and the .NET Platform, 2. C# Language Fundamentals

51 de 96

C# Control Flow Constructs (3)


A outra construo simples para seleco oferecida pelo C# a instruo switch. Esta instruo permite controlar o fluxo do programa com base num conjunto de opes prdefinidas. Por exemplo, a seguinte aplicao questiona o utilizador por um de trs valores possveis:
// The good o1switch statement. class Selections { public static void Main() { Console.WriteLine("Welcome to the world of .NET"); Console.WriteLine("1 = C#\n2 = Managed C++ (MC++)\n"3 = VB.NET\n"); Console.Write("Please select your implementation language: "); string s = Console.ReadLine(); // All intrinsic data types support a static Parse() method. int n = int.Parse(s); switch (n) { // C# demands that each case (including 'default') which contains // executable statements, must have a terminating 'break' or 'goto' // to avoid fall through. case 1: Console.WriteLine("Good choice! C# is all about managed code."); break; case 2: Console.WriteLine("Let me guess, maintaining a legacy system?"); break; case 3: Console.WriteLine("VB.NET: It is not just for kids anymore..."); break; default: Console.WriteLine("Well... good luck with that!"); break; } } }

Autor: Andrew Troelsen Traduo: Carlos Martins

C# and the .NET Platform, 2. C# Language Fundamentals

52 de 96

Additional C# Operators (1)


C# define um conjunto de operadores para alm daqueles que analismos anteriormente. De forma geral, esses operadores comportam-se com os operadores correspondentes em C(++) e em Java. A Tabela 2-7 lista os operadores C# pela ordem de precedncia.
Table 2-7. The Full Set of C# Operators Operator Category
Unary Multiplicative Additive Shift Relational Equality Logical AND Logical XOR Logical OR

Operators
+ - ! ~ ++x x++ --x x-* / % + << >> < > <= >= is as == != & ^ |

Conditional AND
Conditional OR Commotional Assignment

&&
|| ?: = *= %= += -= <<= >>= &= ^= |=

Autor: Andrew Troelsen Traduo: Carlos Martins

C# and the .NET Platform, 2. C# Language Fundamentals

53 de 96

Additional C# Operators (2)


Os nicos operadores novos so os operadores is e as. O operador is utilizado para verificar em runtime se um objecto compatvel com determinado tipo. Uma utilizao comum deste operador para determinar se um objecto suporta uma interface particular (como se analisar em detalhe no Captulo 4). O operador as permite fazer downcast entre tipos (tambm analisado no Captulo 4).

Autor: Andrew Troelsen Traduo: Carlos Martins

C# and the .NET Platform, 2. C# Language Fundamentals

54 de 96

Defining Custom Class Methods (1)


Agora vamos analisar como se definem mtodos especficos numa classe C#. Qualquer mtodo tem que ser membro de uma classe ou de uma estrutura. Em C# no so permitidos mtodos globais. Como sabemos, os mtodos existem para permitir ao tipo realizar uma unidade de trabalho. Tal como Main, os mtodos especficos podem, ou no, ter parmetros e podem, ou no, devolver valores. Para comear, cada mtodo deve especificar o seu nvel de acessibilidade (consulte a Tabela 2-8). A seguir apresentam-se as implicaes de cada uma das palavras chave que definem a visibilidade:
// Visibility options. class SomeClass { public void MethodA() {} // Accessible anywhere. private void MethodB() {} // Accessible only from SomeClass types. protected void MethodC() {} // Accessible from Someclass and any descendent. internal void MethodD() {} // Accessible from within the same assembly. protected internal void MethodE() {} // Internal or protected access. void MethodF() {} // Private by default. }

Method Access Modifiers


Autor: Andrew Troelsen Traduo: Carlos Martins

C# and the .NET Platform, 2. C# Language Fundamentals

55 de 96

Defining Custom Class Methods (2)


Table 2-8. C# Accessibility Keywords C# Access Modifier public private Meaning in Life Marks a method as accessible from an object instance, or any subclass. Marks a method as accessible only by the class that has defined the method. If you dont say otherwise, private is assumed (it is the default visibility level). Marks a method as usable by the defining class, as well as any child class, but if private as far as the outside world is concerned. Defines a method that is publicly accessible by all types in an assembly (but not from outside assembly). Protected access or internal access.

protected internal protected internal

Os mtodos que so declarados pblicos so acessveis directamente a partir de uma instncia do objecto. Os mtodos privados no podem ser acedidos a partir de uma instncia de um objecto, mas apenas chamados internamente para ajudar a instncia a fazer o seu trabalho (isto , funes auxiliares privadas). Para ilustrar, a classe Teenager mostrada a seguir define dois mtodos pblicos, Complain e BeAgreeable, cada um dos quais devolve um string ao utilizador do objecto.
C# and the .NET Platform, 2. C# Language Fundamentals
56 de 96

Autor: Andrew Troelsen Traduo: Carlos Martins

Defining Custom Class Methods (3)


Internamente cada mtodo utiliza um mtodo auxiliar privado chamado GetRandomNumber, que manipula uma varivel membro privada do tipo System.Random:
// Two public methods, each using an internal helper function. using System; class Teenager { // The System.Random type generates random numbers. private static Random r = new Random(); public string Complain() { string[] messages = new string[5]{"Do I have to?", "He started it!", "Im too tired...", "I hate scholl", "You are soon wrong."}; return messages[GetRandomNumber(5)]; } public string BeAgreeable() { string[] messages = new string[3]{"Sure! No problem!", "Uh ug.", "I guess so."}; return messages[GetRandomNumber(3)]; } // Private function used to grab a random number. private static int GetRandomNumber(short upperLimit) { // Random.Next() returns a random integer between 0 and upperLimit return r.Next(upperLimit); } public static void Main() { // Let Mike complain. Teenager mike = new Teenager(); for (int i = 0; i < 10; i++) Console.WriteLine(mike.Complain()); } }

Autor: Andrew Troelsen Traduo: Carlos Martins

C# and the .NET Platform, 2. C# Language Fundamentals

57 de 96

Defining Custom Class Methods (4)


O benefcio de se definir GetRandomNumber como mtodo auxiliar privado o de permitir s vrias partes da classe Teenager usar a respectiva funcionalidade. A alternativa seria duplicar a lgica do nmero aleatrio nos mtodos Complain e BeAgreeable. Repare na utilizao do tipo System.Random. Este tipo gera e manipula nmeros aleatrios. O mtodo Random.Next devolve um nmero entre 0 e o limite superior especificado. Como ser de esperar, o tipo Random define outros membros, documentados no Online Help.

Autor: Andrew Troelsen Traduo: Carlos Martins

C# and the .NET Platform, 2. C# Language Fundamentals

58 de 96

Static Methods and Instance Methods (1)


Os mtodos podem ser declarados static. O que significa mtodo esttico? Quando um mtodo marcado com a palavra chave static, pode ser invocado sem ser necessrio dispor de uma instncia do objecto. O mtodo Main declarado esttico para permitir que o runtime o invoque sem ser necessrio criar uma instncia da classe que o define. Para ilustrar a utilizao de mtodos estticos especficos, assuma que rescrevemos o mtodo Complain do seguinte modo:
// Teenagers complain so often, there is no need to create an initial object. public static string Complain() { string[] messages = new string[5]{"Do I have to?", "He started it!", "Im too tired...", "I hate scholl", "You are soon wrong."}; return messages[GetRandomNumber(5)]; }

Para invocar um mtodo esttico basta preceder o nome do membro do nome da classe:
// Call the static Complain method of the Teenager class. public static void Main () { for (int i = 0; i < 10; i++) Console.WriteLine(Teenager.Complain()); }

Os mtodos no estticos (de instncia) so mtodos do nvel objecto. Se Complain no for marcado com esttico, ser necessrio criar uma instncia da classe Teenager para ser possvel a respectiva invocao:
// Must make an instance of Teenager class to call instance methods. Teenager joe = new Teenager(); joe.Complain();

Autor: Andrew Troelsen Traduo: Carlos Martins

C# and the .NET Platform, 2. C# Language Fundamentals

59 de 96

Static Methods and Instance Methods (2)


Defining Static Data
Para alm dos mtodo estticos, uma classe C# pode tambm definir membros dados estticos. Recorde que a classe define tipicamente um conjunto de informao de estado. Isto significa que cada objecto mantm a sua cpia dessa informao. Assim, se tivermos uma classe definida do seguinte modo:
// We all love Foo. class Foo { public int intFoo; }

podemos criar alguns objectos do tipo Foo e definir o campo intFoo com valores diferentes:
// Each Foo reference contains a copy of the intFoo field. Foo f1 = new Foo(); f1.intFoo = 100; Foo f2 = new Foo(); f2.intFoo = 993; Foo f3 = new Foo(); f3.intFoo = 6;

Os dados estticos, por outro lado, so partilhados por todas as instncias da classe. Em vez de cada objecto armazenar uma cpia de um dado campo, existe apenas uma cpia partilhada por todas as instncias da classe.

Autor: Andrew Troelsen Traduo: Carlos Martins

C# and the .NET Platform, 2. C# Language Fundamentals

60 de 96

Static Methods and Instance Methods (3)


Assuma que temos uma classe chamada Airplane que contm um membro dados esttico, que incrementado no construtor:
// Note the use of static keyword. class Airplane { // This static data member is shared by all Airplane objects. private static int NumberInTheAir = 0; public Airplane() { NumberInTheAir++; } // Get value from an object instance. public int GetNumberFromObject() { return NumberInTheAir; } // Get value from class. public static int GetNumber() { return NumberInTheAir; } }

Nesta classe so definidos dois mtodos: o mtodo esttico GetNumber devolve o nmero corrente de objectos aeroplano que foram reservados pela aplicao; o mtodo de instncia GetNumberFromObject tambm devolve o valor do membro esttico. Contudo, uma vez que o segundo mtodo no definido como esttico, o utilizador do objecto ter que o invocar a partir de uma instncia de Airplane. Para ilustrar, observe a seguinte utilizao:

Autor: Andrew Troelsen Traduo: Carlos Martins

C# and the .NET Platform, 2. C# Language Fundamentals

61 de 96

Static Methods and Instance Methods (4)


// Make some Airplanes and examine the static members. class StaticApp { public static void Main() { // Make some planes Airplane a1 = new Airplane(); Airplane a2 = new Airplane(); // How many are in flight? Console.WriteLine("Number of planes: {0}", a1.GetNumberOfObjects()); Console.WriteLine("Number of planes: {0}", Airplane.GetNumber()); // More planes! Airplane a3 = new Airplane(); Airplane a4 = new Airplane(); // Now how many? Console.WriteLine("Number of planes: {0}", a3.GetNumberOfObjects()); Console.WriteLine("Number of planes: {0}", Airplane.GetNumber()); } }

Como podemos observar executando este programa, todas as instncias da classe Airplane partilham a mesma varivel. Esta a razo de ser dos dados estticos: permitir a partilha do membro por todas as instncias da classe.

Autor: Andrew Troelsen Traduo: Carlos Martins

C# and the .NET Platform, 2. C# Language Fundamentals

62 de 96

Static Methods and Instance Methods (5)


An Interesting Aside: Some Static Members of the Environment Class
A classe Environment definida pelo namespace System. Esta classe representa um tipo que expe alguns detalhes relativamente ao sistema operativo da mquina onde executa a aplicao .NET. Cada detalhe obtido usando vrios membros estticos:
// Here are some (but not all) of the interesting static members // of the Environment class. using System; class PlatformSpy { public static void Main() { // OS? Console.WriteLine("Current OS; {0}", Environment.OSVersion); // Directory? Console.WriteLine("Current Directory: {0}", Environment.CurrentDirectory); // Here are the drives on this machine. string[] drives = Environment.GetLogicalDrives(); for (int i = 0; i < drives.Length; i++) Console.WriteLine("Drive {0} : {1}", i, drives[i]); // Which version of the .NET platform? Console.WriteLine("Current version of .NET: {0}", Environment.Version); } }

Autor: Andrew Troelsen Traduo: Carlos Martins

C# and the .NET Platform, 2. C# Language Fundamentals

63 de 96

Method Parameter Modifiers (1)


Os mtodos podem ter parmetros. Quem tem conhecimentos de COM conhece os atributos IDL [in], [out] e [in, out]. Os objectos COM usam estes atributos para definir de forma no ambgua a direco do trfego (e as regras de alocao de memria) para os parmetros dos mtodos das interfaces. Embora o IDL no seja usado no universo .NET, existe um comportamento anlogo, e so usados os modificadores de parmetros mostrados na Tabela 2-9.
Table 2-9. C# Parameter Modifiers Parameter Modifier [none] Meaning in Life If the parameter is not marked with a parameter modifier, it is assumed to be an input parameter passed by value. This is analogous to the IDL [in] attribute. This is analogous to an IDL [out] parameter. Output parameters are assigned by the called member. Analogous to the IDL [in, out] attribute. This value is assigned by the caller,but may be reassigned during the scope of the method call. This parameter modifier allows you to send in a variable number of parameters as a single parameter. A given method can only have a single params modifier, and must be the final parameter of the method. This is (roughly) analogous to a COM SAFEARRAY.

out ref params

Autor: Andrew Troelsen Traduo: Carlos Martins

C# and the .NET Platform, 2. C# Language Fundamentals

64 de 96

Method Parameter Modifiers (2)


Primeiro, vamos discutir a utilizao dos parmetros de entrada e sada com tipos intrnsecos. Aqui se apresenta uma verso do mtodo Add que devolve a soma de dois inteiros e usa a palavra chave out do C#:
// Output parameters are allocated by the caller public void Add(int x, int y, out int ans) { ans = x + y; }

Invocando um mtodo com parmetros de sada tambm requer a utilizao da palavra chave out. Por exemplo:
// Assume the Add() method is defined in a class named Methods. public static void Main() { ... Methods m = new Methods(); int ans; // No need to assign before when a variable is used ala out. // Note the use of out keyword is calling syntax. m.Add(90, 90, out ans); Console.WriteLine("90 + 90 = {0}", ans); }

Os parmetros referncia so necessrios quando pretendemos que um mtodo opere (e altere os valores) de vrios parmetros (como por exemplo, uma rotina de ordenao). Recorde e distino entre parmetros de entrada e parmetros de sada: Os parmetros de sada no necessitam de ser iniciados antes de serem enviados ao callee. Razo: assume-se que o mtodo preenche os valores antes de retornar. C# and the .NET Platform, 2. C# Language Fundamentals
65 de 96

Autor: Andrew Troelsen Traduo: Carlos Martins

Method Parameter Modifiers (2)


Os parmetros referncia devem se iniciados antes de serem enviados ao callee.
Razo: estamos a passar uma referncia para uma instncia existente. Se no lhe atribuir um valor inicial, isso ser equivalente a operar sobre um apontador NULL. Ilustrando a utilizao desta palavra chave:
// Reference parameter. public void UpperCaseThisString(ref string s) { // Return the uppercase version of the string. s = s.ToUpper(); } // ...meanwhile back in Main()... public static void Main() { ... // Use 'ref'. string s = "Can you really have sonic hearing for #19.00?"; Console.WriteLine("Before: {0}", s); m.UpperCaseThisString(ref s); Console.WriteLine("After: {0}", s); }

O ltimo modificador dos parmetros a palavra chave params, que sendo algo invulgar, bastante conveniente na medida em que permite passar um nmero varivel de parmetros sobre um nico parmetro. Assuma que escrevemos um mtodo do seguinte modo:

Autor: Andrew Troelsen Traduo: Carlos Martins

C# and the .NET Platform, 2. C# Language Fundamentals

66 de 96

Method Parameter Modifiers (3)


// This method has two physical parameters. public void DisplayArrayOfInts(string msg, params int[] list) { Console.WriteLine(msg); for (int i = 0; i < list.Length; i++) Console.WriteLine(list[i]); }

Este mtodo foi definido de forma a tomar dois parmetros fsicos: um do tipo string e outra como um array de inteiros parametrizado. O que este mtodo est a dizer de facto : enviem-me um string como primeiro parmetro e qualquer nmero de inteiros como segundo parmetro. Podemos invocar o mtodo de vrias formas:
// Use 'params' keyword. int[] intArray = new int[3]{10, 11, 12}; m.DisplayArrayOfInts("Here is an array of ints", intArray); m.DisplayArrayOfInts("Enjoy these 3 ints", 1, 2, 3); m.DisplayArrayOfInts("Take some more!", 55, 4, 983, 10432, 99, 33);

Analisando o cdigo anterior podemos constatar que os itens a cheio em cada invocao do mtodo correspondem ao segundo parmetro (o array de inteiros). Naturalmente que no obrigatrio usar apenas valores numricos quando utiliza a palavra chave params. Considere a classe Person com a seguinte definio:

Autor: Andrew Troelsen Traduo: Carlos Martins

C# and the .NET Platform, 2. C# Language Fundamentals

67 de 96

Method Parameter Modifiers (3)


// Yet another person class. class Person { private string fullName; private byte age; public Person(string n, byte a) {fullName = n; age = a; } public void PrintInfo() { Console.WriteLine("{0} is {1} years old", fullName, age); } }

Assuma tambm que a classe Methods define outro mtodo que utiliza a palavra chave params, mas desta vez especificando um array de objectos. O cdigo deste mtodo o seguinte::
// What did they send to me this time? public void DisplayArrayOfObjects(params object[] list) { for (int i = 0; i < list.Length; i++) if (list[i] is Person) // Is the current item a Person type? ((Person)list[i]).PrintInfo(); // If so, call some method. else Console.WriteLine(list[i]); Console.WriteLine(); }

A lgica de chamada poder ser a seguinte:


// Make some objects. Person p = new Person("Fred", 87); m.DisplayArrayOfObjects(777, p, "I really am an instance of System.String");

Autor: Andrew Troelsen Traduo: Carlos Martins

C# and the .NET Platform, 2. C# Language Fundamentals

68 de 96

Array Manipulation in C# (1)


Os arrays C# tm um aspecto semelhantes aos seus pares em C++ ou Java. Como veremos adiante, os arrays C# derivam da classe base System.Array e, por isso, partilham um conjunto de membros. Formalmente, um array uma coleco de pontos de dados (com o mesmo tipo) que podem ser acedidos usando um ndice numrico. Os arrays podem conter qualquer tipo intrnseco de dados do C#, incluindo arrays de objectos, de interfaces ou de estruturas. Em C# os arrays podem ser simples ou multidimensionais, e so declarados usando parntesis rectos ([]) depois do tipo de dados do array. Por exemplo:
// A string array containing 10 elements {0, 1, ..., 9} string[] booksOnCOM; booksOnCOM = new string[10]; // A 2 item string array, numbered {0, 1} string[] booksOnPL1 = new string[2]; // 100 item string array, numbered{0, 1, ..., 99} string[] booksOnDotNet = new string[100];

O primeiro exemplo declara o tipo e a dimenso do array em duas linhas separadas. Nos dois ltimos exemplos, mostra-se que possvel declarar e construir o array numa nica linha (assim como qualquer outro objecto). Em qualquer dos casos, repare que necessrio usar a palavra chave new quando se constri o array com uma dimenso inicial fixa. Assim, a seguinte declarao ilegal:
// Need 'new' keyword when you define a fixed size array. int[4] ages = {30, 54, 8, 10}; // Error!

Autor: Andrew Troelsen Traduo: Carlos Martins

C# and the .NET Platform, 2. C# Language Fundamentals

69 de 96

Array Manipulation in C# (2)


A dimenso do array fixada quando o array criado, no quando declarado. Por isso, quando se pretende declarar um array com dimenso inicial fixa, necessrio usar o operador new. No entanto, podemos deixar ao compilador a determinao da dimenso do array, usando a seguinte notao:
// The size of this array will automatically be set to 4. // Note the lack of the 'new' keyword and empty []. int[] ages = {20, 22, 23, 0};

Na iniciao dos membros de um array possvel usar a notao das chavetas ({}) em alternativa atribuio de valores a cada membro a membro, pelo que os dois arrays seguintes so idnticos:
// Initialize each member at declaration OR... string[] firstNames = new string[5]{"Steve", "Gina", "Swallow", "Baldy", "Gunner"}; // ...assign values member by member. string[] firstNames = new string[5]; firstNames[0] = "Steve"; firstNames[1] = "Gina"; firstNames[2] = "Swallow"; firstNames[3] = "Baldy"; firstNames[4] = "Gunner";

Um ltima diferena entre os arrays C++ e os arrays C# que todos os seus elementos so afectados automaticamente com o valor por omisso. Por exemplo, num array de tipos numricos, todos os elementos so iniciados com 0, nos arrays de objectos, os elementos so iniciados com null, e assim sucessivamente. C# and the .NET Platform, 2. C# Language Fundamentals
70 de 96

Autor: Andrew Troelsen Traduo: Carlos Martins

Array Manipulation in C# (3)


Working with Multidimensional Arrays
Para alm dos arrays unidimensionais, o C# suportam tambm dois tipos de arrays multidimensionais. O primeiro tipo designado por array rectangular e trata-se simplesmente de um array com vrias dimenses. Para declarar e preencher um array rectangular multidimensional, procedemos do seguinte modo:
// A rectangular MD array. int[,] myMatrix; myMatrix = new int[6, 6]; // Populate (6 * 6) array. for (int i = 0; i < 6; i++) for (int j = 0; j < 6; j++) myMatrix[i, j] = i * j; // Show (6 * 6) array. for (int i = 0; i < 6; i++) { for (int j = 0; j < 6; j++) Console.WriteLine(myMatrix[i, j] + "\t"); Console.WriteLine(); }

O segundo tipo de arrays multidimensionais so designados por jagged array. Como o prprio nome indica, os jagged arrays contm arrays internos, em que cada um poder ter um limite superior prprio. Por exemplo:

Autor: Andrew Troelsen Traduo: Carlos Martins

C# and the .NET Platform, 2. C# Language Fundamentals

71 de 96

Array Manipulation in C# (4)


// A jagged MD array (i.e. an array of arrays). // Here we have an array of 5 different arrays. int[][] myJagArray = new int[5][]; // Create the jagged array. for (int i = 0; i < myJagArray.Length; i++) myjagArray[i] = new int[i + 7]; // Print each row (remember, each element is defaulted to zero!) for (int i = 0; i < 5; i++) { Console.WriteLine("Length of row {0} is {1}:\t", myJagArray[i].Length); for (int j = 0; j < myJagArray[i].Length; j++) Console.WriteLine(myJagArray [i][j] + "\t"); Console.WriteLine(); }

Aps perceber como se constrem e preenchem os arrays C#, vamos analisar a classe base de todos os arrays, System.Array. A diferena mais importante entre os arrays C++ e os arrays C# o facto de que estes ltimos derivarem automaticamente da classe System.Array. Esta classe define um conjunto de mtodos que tornam a manipulao dos arrays mais agradvel. A Tabela 210 enumera alguns dos membros mais interessantes. Vamos exemplificar a utilizao de alguns destes membros. O seguinte cdigo utiliza os mtodos estticos Reverse, Clear e a propriedade Length para mostrar na consola informao acerca do array firstName: C# and the .NET Platform, 2. C# Language Fundamentals
72 de 96

The System.Array Base Class

Autor: Andrew Troelsen Traduo: Carlos Martins

Array Manipulation in C# (5)


Table 2-10. Selected Members of System.Array Member of Array Class BinarySearch Clear CopyTo GetEnumerator Meaning in Life This static method is applicable only if the items in the array implement the IComparer interface. If so, BinarySearch() finds a given item. This static method set a range of elements in the array to empty values (0 for value items, null for object references). Used to copy elements from the source array into the destination array. Returns the IEnumerator interface for a given array. I address interfaces in Chapter 4, but for the time being, keep in mind that this interface is required for the foreach construct. The GetLength() method is used to determine the number of elements in a given dimension of the array. Length is a read-only property. As you can guess, these two methods can be used to determine the bounds of a given dimension. Retrieves or sets the value for a given index in the array. These methods have been overloaded to work with a single and multidimensional arrays This static method reverses the contents of a one-dimensional array. Sorts a one-dimensional array of intrinsic types. If the elements of the array implement the IComparer interface, you can also sort custom types.

GetLength Length GetLowerBound GetUpperBound GetValue SetValue Reverse Sort

Autor: Andrew Troelsen Traduo: Carlos Martins

C# and the .NET Platform, 2. C# Language Fundamentals

73 de 96

Array Manipulation in C# (6)


// Create some string arrays and exercises some System.Array members. class Arrays { public static void Main() { // Array of strings. string[] firstNames = new string[5]{"Steve", "Gina", "Swallow", "Baldy", "Gunner"}; // Print out names in declared order. Console.WriteLine("Here is the array:"); for (int i = 0; i < firstNames.Length; i++) Console.WriteLine(firstNames[i] + "\t"); // Flip things around using the static Reverse() method... Array.Reverse(firstNames); // ... and print them. Console.WriteLine("Here is the array:"); for (int i = 0; i < firstNames.Length; i++) Console.WriteLine(firstNames[i] + "\t"); // Clear out but young gunner. Console.WriteLine("Cleared out all but one... "); Array.Clear(firstNames, 1, 4); for (int i = 0; i < firstNames.Length; i++) Console.WriteLine(firstNames[i] + "\t"); } }

A possibilidade de tratar os arrays como objectos foi um luxo permitido aos programadores Java (entre outros). O C# e a plataforma .NET permite agora aos projectistas tradicionais de Windows dispem dos mesmos benefcios (podendo esquecer de vez o SAFEARRAY COM).
C# and the .NET Platform, 2. C# Language Fundamentals
74 de 96

Autor: Andrew Troelsen Traduo: Carlos Martins

String Manipulation in C# (1)


O string um tipo de dados intrnseco do C#. No entanto, tal como todos os tipos de dados intrnsecos, o string sinnimo do tipo System.String, definido na biblioteca de classes base. Esta classe define o conjunto de mtodos expectveis numa classe utilitria, como sejam mtodos para devolver a dimenso, localizar sub-strings, converter para maisculas/minsculas, etc.. A Tabela 2-11 lista alguns dos membros da classe System.String. necessrio ter presente alguns aspectos da manipulao de strings C#. Primeiro, embora string seja um tipo referncia, os operadores de igualdade (== e !=) esto definidos com semntica baseada no valor. O operador mais (+) foi sobrecarregado para uma forma abreviada de invocar o mtodo Concat:
// == and != are used to compare the values within strings. // + is used for concatenation. public static void Main() { System.String strObj = "This is a TEST"; string s = "This is another TEST"; // Test for equality between strings. if (s == strObj) Console.WriteLine("Same info..."); else Console.WriteLine("Not the same info..."); // Concatenation string newString = s + strObj; Console.WriteLine("s + strObj = {0}", newString);

Autor: Andrew Troelsen Traduo: Carlos Martins

C# and the .NET Platform, 2. C# Language Fundamentals

75 de 96

String Manipulation in C# (2)


// System.String also defines a custom indexer to access each character // in the string. for (int k = 0; k < s.Length; k++) Console.WriteLine("Char {0} is {1}", k, s[k]); return 0; }

Quando se executar este programa,verificar que os objectos string (s e strObj) no contm os mesmos valores e, por isso, o teste pela igualdade falha. Quando examinar o contedo de newString ver This is another TESTThis is a TEST. Finalmente, demonstra-se o acesso aos caracteres do string usando o operador ndice ([]).

Escape Characters and Verbatim Strings Assim como em C++ e em Java, os strings C# podem conter caracteres escape.
// Escape characters (\t, \\, \n, et al.) string anotherString; anotherString = "Every programming book needs \"Hello World\""; Console.WriteLine("\t" + anotherString); anotherString = "c:\\CSharpProjects\\Strings\\string.cs"; Console.WriteLine("\t" + anotherString);

Para quem estiver um pouco esquecido dos caracteres escape, a Tabela 2-12 ajuda a refrescar a memria.

Autor: Andrew Troelsen Traduo: Carlos Martins

C# and the .NET Platform, 2. C# Language Fundamentals

76 de 96

String Manipulation in C# (3)


Table 2-11. Select Members of System.String Member of Array Class Length Concat CompareTo Copy Format Insert PadLeft PadRight Remove Replace ToUpper ToLower Meaning in Life This property returns the length of the current string. This static method of the String class returns a new string that is composed of two discrete strings. Compares two strings. This static method returns a fresh new copy of a existing string. Used to format a string using other primitives (i.e., numerical data, other strings) and the {0} notation examined earlier in this chapter.. Used to insert a string within a given string.. This methods are used to pad a string with some character. Use these methods to receive a copy of a string, with modifications (characters removed or replaced). Creates a copy of a given string using uppercase or lowercase.

Autor: Andrew Troelsen Traduo: Carlos Martins

C# and the .NET Platform, 2. C# Language Fundamentals

77 de 96

String Manipulation in C# (4)


Table 2-12. String Escape Characters Escape Character \' \" \\ \a \b \f \n \r \t \u \v \0 Meaning in Life Inserts a single quote into a string literal. Inserts a double quote into a string literal. Inserts a backslash into a string literal. This can be quite helpful when defining file paths. Triggers a system alert. Triggers a backspace. Triggers a form feed. Inserts a new line. Inserts a carriage return. Inserts a horizontal tab into the string literal. Inserts a Unicode character into the string literal. Inserts a vertical tab into the string literal. Represents a NULL character.

Autor: Andrew Troelsen Traduo: Carlos Martins

C# and the .NET Platform, 2. C# Language Fundamentals

78 de 96

String Manipulation in C# (5)


Para alm dos caracteres de escape tradicionais, o C# introduz a notao @-quoted string literal. Os strings expressos com o prefixo @ so designados verbatim strings. Usando estes strings, possvel fazer bypass ao processamento dos caracteres escape, e definir os literais da seguinte forma:
// The @string turns of the preprocessing of escape characters. string finalString = @"\n\tString file: 'C:\CSharpProjects\Strings\string.cs"; Console.WriteLine(finalString);

Ao verificar o output desta ltima instruo pode constatar com os caracteres de escape no so processados nos strings definidos com o prefixo @. Using System.Text.StringBuilder Existe um facto que devemos ter sempre presente quando usamos strings C#: aps estabelecido o valor de um string este no pode ser modificado (o que tambm acontece na linguagem Java). Ao analisar os mtodos da classe System.String, constatamos que os mtodos que parecem modificar internamente o string, na realidade devolvem uma cpia do string original com as alteraes. Por exemplo, quando se enviar a mensagem ToUpper para o objecto string, este no modificar o contedo do seu buffer; constri uma cpia do string em letras maisculas:
// Make changes to this string? Not really... System.String strFixed = "This is how I began life"; Console.WriteLine(strFixed); string upperVersion = strFixed.ToUpper(); // Returns an uppercase copy of Console.WriteLine(strFixed); Console.WriteLine(upperVersion);

Autor: Andrew Troelsen Traduo: Carlos Martins

C# and the .NET Platform, 2. C# Language Fundamentals

79 de 96

String Manipulation in C# (6)


claramente ineficiente trabalhar com cpias de cpias de strings. Para obviar a este inconveniente, o namespace System.Text define a classe StringBuilder. Esta classe funciona de forma semelhante ao CString do MFC ou ao CComBSTR do ATL, onde as modificaes feitas s instncias de StringBuilder provocam alteraes efectivas no buffer interno.
// Play with the StringBuilder class. using System; using System.Text; // StringBuilder lives here! class StringApp { public static void Main() { // Create a StringBuilder and change the underlying buffer. StringBuilder myBuffer = new StringBuilder("I am a buffer"); myBuffer.Append(" that just got longer..."); Console.WriteLine(myBuffer); } }

Alm de permitir acrescentar informao ao buffer interno, a classe StringBuilder permite substituir e remover caracteres. Aps ter sido estabelecido o contedo pretendido com um objecto StringBuilder, podemos invocar ToString para armazenar o respectivo contedo num objecto do tipo System.String.

Autor: Andrew Troelsen Traduo: Carlos Martins

C# and the .NET Platform, 2. C# Language Fundamentals

80 de 96

String Manipulation in C# (7)


// Play with the StringBuilder class. using System; using System.Text; // StringBuilder lives here! class StringApp { public static void Main() { // Play with the StringBuilder class some more... StringBuilder myBuffer = new StringBuilder("I am a buffer"); myBuffer.Append(" that just got longer..."); Console.WriteLine(myBuffer); myBuffer.Append("and even longer."); Console.WriteLine(myBuffer); // Transfer the buffer to an uppercase fixed string. string theReallyFinalString = myBuffer.ToString().ToUpper(); Console.WriteLine(theReallyFinalString); } }

Como deve adivinhar, a classe StringBuilder contm mtodos e propriedades que aqui no foram referidas. Deixamos ao cuidado do leitor o aprofundamento do conhecimento sobre esta classe.

Autor: Andrew Troelsen Traduo: Carlos Martins

C# and the .NET Platform, 2. C# Language Fundamentals

81 de 96

C# Enumerations (1)
frequente a necessidade de criar um conjunto de nomes a que esto associados valores numricos. Por exemplo, se estivermos a criar uma sistema para pagamento de vencimentos, podemos necessitar das constantes VP, Manager, Grunt e Contractor em vez de valores numricos puros {0, 1, 2, 3}. Tal como o C++, C# suporta a noo de enumerao especfica. Por exemplo, a definio da enumerao EmpType:
// A custom enumeration. enum EmpType { Manager, // = 0 Grunt, // = 1 Contractor, // = 2 VP // = 3 }

A enumerao EmpType define quatro constantes com nome, correspondendo a valores numricos discretos. Em C#, o esquema de numerao atribui zero ao primeiro elemento, seguida por uma progresso de n+1. Podemos alterar esse comportamento do seguinte modo:
// Begin with 102. enum EmpType { Manager = 102, Grunt, // = 103 Contractor, // = 104 VP // = 105 }

Autor: Andrew Troelsen Traduo: Carlos Martins

C# and the .NET Platform, 2. C# Language Fundamentals

82 de 96

C# Enumerations (2)
As enumeraes no necessitam de seguir uma numerao sequencial. Se, por alguma razo, fizer sentido estabelecer o tipo EmpType como se mostra a seguir, isso possvel.
// Elements of an enumeration need not be sequential! enum EmpType { Manager = 10, Grunt = 1, Contractor = 100, VP = 9 }

O tipo usado para armazena o enumerado por omisso um inteiro, embora seja possvel escolher outro tipo. Por exemplo, se pretender armazenar o enumerador num byte em vez de um int, dever escrever o seguinte:
// This time, EmpType maps to an underlying byte. enum EmpType : byte { Manager = 10, Grunt = 1, Contractor = 100, VP = 9 }

Os enumeradores podem ser definidos de forma semelhante para usar qualquer outro tipo base (byte, sbyte, short, int, etc.).

Autor: Andrew Troelsen Traduo: Carlos Martins

C# and the .NET Platform, 2. C# Language Fundamentals

83 de 96

C# Enumerations (3)
Uma vez estabelecida a gama e o tipo para armazenamento da enumerao, esta poder ser usada como magic-number. Assuma que tem uma classe que define um mtodo pblico esttica que toma EmpType como parmetro:
using System; class EnumClass { public static void AskForBonus(EmpType e) { switch (e) { case EmpType.Contractor: Console.WriteLine("You already get enough cash..."); break; case EmpType.Grunt: Console.WriteLine("You have got to be kidding..."); break; case EmpType.Manager: Console.WriteLine("How about stock options instead..."); break; case EmpType.VP: Console.WriteLine("VERY GOOD, Sir!"); break; default: } } public static void Main() { // Make a contractor type EmpType fred; fred = EmpType.Contractor; AskForBonus(fred); } }

Autor: Andrew Troelsen Traduo: Carlos Martins

C# and the .NET Platform, 2. C# Language Fundamentals

84 de 96

C# Enumerations (4)
System.Enum Base Class
Todas as enumeraes C# derivam implicitamente da classe System.Enum. Esta classe base define um conjunto de mtodos que permitem a interrogao e a transformao das enumeraes. O mtodo esttico GetUnderlyingType devolve o tipo de dados usado para armazenar a enumerao:
// Get underlying type (System.Byte for the current example) Console.WriteLine(Enum.GetUnderlyingType(typeof(EmpType)));

A possibilidade de obter o nome das constantes a partir dos valores numricos tem, por vezes, interesse. frequente ser necessrio transformar uma enumerao C++ nos strings subjacentes. Em C# isso torna-se trivial usando o mtodo esttico Enum.Format. No exemplo anterior, a varivel fred foi estabelecida como Contractor (que corresponde ao valor de 100). Para extrair o string correspondente, invoca-se Enum.Format especificando o tipo da enumerao a investigar e uma flag que especifica o formato. Neste contexto, G define um valor do tipo string. possvel obter tambm um valor hexadecimal (x) ou decimal (d).
// The following pumps the string "You are a Contractor" to the console. EmpType fred; fred = EmpType.Contractor; Console.WriteLine("You are a {0}", Enum. Format(typeof(EmpType), fred, "G");

Autor: Andrew Troelsen Traduo: Carlos Martins

C# and the .NET Platform, 2. C# Language Fundamentals

85 de 96

C# Enumerations (5)
System.Enum define tambm o mtodo esttico GetValues que devolve uma instncia de System.Array. Cada item do array corresponde a um membro da enumerao:
// Get all statistics for the EmpTYpe enumeration. Array obj = Enum.GetValues(typeof(EmpType)); Console.WriteLine("This enum as {0} members.", obj.Length); // Now show the string name and associated value foreach(EmpType e in obj) { Console.Write("String name: {0}", Enum.Format(typeof(EmpType), e, "G")); Console.Write(" ({0})", Enum.Format(typeof(EmpType), e, "D")); Console.Write(" hex: {0}\n", Enum.Format(typeof(EmpType), e, "X")); }

Vamos agora explorar o mtodo IsDefined. Este mtodo permite determinar se um dado string define, ou no, um nome na enumerao especificada:
// Does EmpType have a SalePerson value? if (Enum.IsDefined(typeof(EmpType), "SalesPerson")) Console.WriteLine("Yep, we have sales people.") else Console.WriteLine("No, we have no profits...");

Por ltimo, vale a pena realar que as enumeraes C# suportam a utilizao de vrios operadores sobrecarregados que testam os valores associados:
// Which of these two EmpType variables has the greatest numerical value? EmpType Joe = EmpType.VP; EmpType Fran = EmpType.Grunt; if (Joe < Fran) Console.WriteLine("Joe's value is less that Fran's"); else Console.WriteLine("Fran's value is less than Joe's");

Autor: Andrew Troelsen Traduo: Carlos Martins

C# and the .NET Platform, 2. C# Language Fundamentals

86 de 96

Defining Structures in C# (1)


Embora j tivssemos feito referncia s estruturas necessrio uma segunda abordagem. As estruturas C# comportam-se de forma semelhante s classes especficas: podem ter construtores (desde que estes tenham argumentos); podem implementar interfaces; e podem conter vrios membros. As estruturas C# no tm um nome que lhes seja sinnimo na biblioteca .NET (isto , no existe nenhum tipo System.Structure), mas derivam implicitamente de System.ValueType. Lembre-se que o papel da classe System.ValueType redefinir os membros de System.Object com semntica baseada em valor. Deixamos aqui um exemplo simples :
// Our existing enumeration. enum EmpType : byte { Manager = 10, Grunt = 1, Contractor = 100, VP = 9 } struct EMPLOYEE { public EmpType title; // One of the fields is our custom enum. public string name; public short deptID; } class StructTester { public static void Main() { // Create and format Fred. EMPLOYEE fred; fred.deptID = 40; fred.name = "Fred"; fred.title = EmpType.Grunt; } }

Autor: Andrew Troelsen Traduo: Carlos Martins

C# and the .NET Platform, 2. C# Language Fundamentals

87 de 96

Defining Structures in C# (2)


Crimos a estrutura EMPLOYEE no stack e manipulmos cada campo usando o operador ponto. Para providenciar uma construo mais optimizada deste tipo, podemos definir construtores adicionais. Tenha em considerao que no possvel redefinir o construtor por omisso da estrutura C#, porque se trata de um membro reservado. Em consequncia, a definio de construtores obriga especificao de parmetros:
// Structs may define custom constructors (if they have args). struct EMPLOYEE { // Fields. public EmpType title; public string name; public short deptID; // Constructor. public EMPLOYEE(EmpType et, string n, short d) { title = et; name = n; deptID = d; } }

Dispondo da definio desta estrutura, podemos criar um novo empregado do seguinte modo:
class StructTester { public static void Main() { // Must use 'new' to call a custom constructor. EMPLOYEE mary = new EMPLOYEE(EmpType.VP, "Mary", 10); ... } }

Autor: Andrew Troelsen Traduo: Carlos Martins

C# and the .NET Platform, 2. C# Language Fundamentals

88 de 96

Defining Structures in C# (3)


As estruturas podem, naturalmente, ser usadas como parmetros em qualquer funo membro. Por exemplo, assuma que a classe StructTest define um mtodo designado DisplayEmpStats:
// Extract interesting information from an EMPLOYEE structure. public void DisplayEmpStats(EMPLOYEE e) { Console.WriteLine("Here is {0}'s info:", e.name); Console.WriteLine(" Department ID: {0}", e.deptID); Console.WriteLine(" Title: {0}", Enum.Format(typeof(EmpType), e.title, "G")); }

Este mtodo poder ser testado da seguinte forma:


// Let Mary & Fred struct their stuff. public static void Main() { ... StructTester t = new StructTester(); t.DisplayEmpStats(mary); t.DisplayEmpStats(fred); ... }

Autor: Andrew Troelsen Traduo: Carlos Martins

C# and the .NET Platform, 2. C# Language Fundamentals

89 de 96

(Un)Boxing Revisited
Como foi referido anteriormente neste captulo, o mecanismo de boxing e unboxing providencia uma forma eficiente de comutar entre tipos valor e tipos referncia. Em geral, as estruturas permitem obter os benefcios da orientao por objectos (i.e., encapsulamento), mantendo a eficincia associada aos dados alojados no stack. Para converter uma estrutura numa referncia para um objecto, basta fazer boxing do valor:
// Create and box a new employee. EMPLYEE stan = new EMPLOYEE(EmpType.Grunt, "Stan", 10); object standInBox = stan;

Uma vez que stanInBox um tipo referncia que mantm os valores internos do tipo original EMPLOYEE, podemos usar stanInBox quando necessrio um objecto e fazer unboxing sempre que seja necessrio:
// Because we have boxed our value data type into a structure, we can // unbox and manipulate the contents. public void UnboxThisEmployee(object o) { // Unbox into EMPLOYEE structure to get at the fields. EMPLOYEE temp = (EMPLOYEE)o; Console.WriteLine(temp.name + " is alive!"); }

Recorde que o compilador de C# faz automaticamente boxing quando necessrio. Por isso, seria permitido passar directamente o tipo EMPLOYEE para UnboxThisEmployee:
// Stan is boxed automatically. t.UnboxThisEmployee(stan);

Autor: Andrew Troelsen Traduo: Carlos Martins

C# and the .NET Platform, 2. C# Language Fundamentals

90 de 96

Defining Custom Namespaces (1)


At agora temos construdo pequenos programas de teste usando os namespaces existentes no universo .NET. Quando se constrem aplicaes reais, til agrupar os tipos relacionados em namespaces especficos. Em C#, isso possvel usando a palavra chave namespace. Assuma que estamos a desenvolver uma coleco de classes geomtricas designadas Square, Circle e Hexagon. Dadas as semelhanas, pretendemos que fiquem agrupadas num nico namespace. Para tal existem de duas solues. Primeiro, definir todas as classe num nico ficheiro (shapeslib.cs), do seguinte modo:
// shapelib.cs namespace MyShapes { using System; // Circle class public class Circle { /* Interesting methods ... */ }; // Hexagon class public class Hexagon { /* Interesting methods ... */ }; // Square class public class Square { /* Interesting methods ... */ }; }

Repare que o namespace MyShapes funciona como contentor de tipos. Em alternativa, possvel partir o mesmo namespace em mltiplos ficheiros C#. Para fazer isso, basta envolver as definies das classes no mesmo namespace.

Autor: Andrew Troelsen Traduo: Carlos Martins

C# and the .NET Platform, 2. C# Language Fundamentals

91 de 96

Defining Custom Namespaces (2)


// circle.cs namespace MyShapes { using System; // Circle class public class Circle { /* Interesting methods ... */ }; } // hexagon.cs namespace MyShapes { using System; // Hexagon class public class Hexagon { /* Interesting methods ... */ }; } // square.cs namespace MyShapes { using System; // Square class public class Square { /* Interesting methods ... */ }; }

Quando outra aplicao desejar usar estes objectos dentro do seu namespace, basta usar a directiva using:
// Make use of objects defined in another namespace. namespace MyApp { using System; using MyShapes; class ShapeTester { ... } }

Autor: Andrew Troelsen Traduo: Carlos Martins

C# and the .NET Platform, 2. C# Language Fundamentals

92 de 96

Defining Custom Namespaces (3)


Resolving Name Clashes Across Namespaces
Os namespaces podem tambm ser utilizados para evitar os conflitos entre os nomes definidos em vrios namespaces. Assuma que a classe ShapeTester pretende usar um novo namespace designado My3DShapes que define trs classes capazes de desenhar as respectivas figuras a trs dimenses:
// Another shapes namespace... namespace My3DShapes { using System; // 3D Circle class public class Circle { ... }; // 3D Hexagon class public class Hexagon { ... }; // 3D Square class public class Square { ... }; }

Se a classe ShapesTester for alterada da forma como se como se mostra a seguir, so assinalados erros de compilao, porque ambos os namespaces definem nomes iguais.
// Ambiguities abound! namespace MyApp { using System; using MyShapes; using My3DShapes;

Autor: Andrew Troelsen Traduo: Carlos Martins

C# and the .NET Platform, 2. C# Language Fundamentals

93 de 96

Defining Custom Namespaces (3)


class ShapeTester { public static void Main() { // Which namespace do I reference? Hexagon h = new Hexagon(); Circle c = new Circle(); Square s = new Square(); ... } }

Para resolver as ambiguidades necessrio usar fully qualified names:


// We have now resolved the ambiguity. public static void Main() { My3dShapes.Hexagon h = new My3DShapes.Hexagon(); My3dShapes.Circle c = new My3DShapes.Circle(); MyShapes.Square s = new MyShapes.Square(); ... }

Defining Namespace Aliases


Tambm possvel resolver ambiguidades namespaces usando aliases. Por exemplo:
namespace MyApp { using System; using MyShapes; using My3DShapes; // Make an alias to a class defined in another namespace. using The3DHexagon = My3DShapes.Hexagon;

Autor: Andrew Troelsen Traduo: Carlos Martins

C# and the .NET Platform, 2. C# Language Fundamentals

94 de 96

Defining Custom Namespaces (4)


class ShapeTester { public static void Main() { My3dShapes.Hexagon h = new My3DShapes.Hexagon(); My3dShapes.Circle c = new My3DShapes.Circle(); MyShapes.Square s = new MyShapes.Square (); // Create a 3D hex using a defined alias: The3DHexagon h2 = new The3DHexagon(); ... } }

Nested Namespaces
A ltima questo com interesse acerca dos namespaces a possibilidade de aninhar um namespace dentro de outro namespace. A biblioteca de classes base do .NET usam esta tcnica para obter um nvel de organizao em profundidade. Por exemplo, se pretender criar um namespace de alto nvel que contenha o namespace My3DShapes pode proceder do seguinte modo:
// The Chapter2Types.My3DShapes namespace contains 3 classes. namespace Chapter2Types { namespace My3DShapes { using System; class Circle { ... } // 3D Circle class class Hexagon { ... } // 3D Hexagon class class Square { ... } // 3D Square class } }

Autor: Andrew Troelsen Traduo: Carlos Martins

C# and the .NET Platform, 2. C# Language Fundamentals

95 de 96

Summary
Este captulo exps os mecanismos nucleares da linguagem de programao C#. Foi dado foco anlise das vrias construes sintcticas que ocorrem em qualquer aplicao. Primeiro, cada programa C# dever definir um mtodo esttico chamado Main, que funciona como entry point do programa. No mbito de Main so tipicamente criados os objectos que funcionam em conjunto para implementar a aplicao. Tambm vimos, que todos os tipos intrnsecos do C# correspondem a um tipo definido no namespace System. Cada tipo definido no .NET tem alguns mtodos e propriedades que permitem, de forma programtica, obter a gama de cada tipo. Foram tambm analisados programas que serviram para estudo das construes e tipos comuns, como arrays, strings, enumeraes etc.. Neste captulo tambm se discutiu o mecanismo de boxing e de unboxing. Este mecanismo permite converter tipos valor em tipos referncia e vice-versa. Finalmente, este captulo termina com a explicao de como se definem namespaces especficos, e discute as razes porque os mesmos devem ser definidos.

Autor: Andrew Troelsen Traduo: Carlos Martins

C# and the .NET Platform, 2. C# Language Fundamentals

96 de 96

Vous aimerez peut-être aussi