You are on page 1of 30

APÊNDICE G

Manual de Sintaxe da Linguagem C#

SUMÁRIO

G.1 Estrutura de um programa em C# G.3 Operadores e expressões


G.2 Sentenças G.4 Exceções

Este apêndice descreve as regras básicas de sintaxe de C# que cumprem as versões do compilador
7.00.9254, contida em Beta 2, ao 7.00.9466, contida na versão 1.0.3705 do SDK.

G.1 ESTRUTURA DE UM PROGRAMA EM C#

A classe é o fundamento da programação orientada a objetos em C#. Uma classe encapsula dados
(representados por variáveis) e comportamentos (representados por métodos). Todo o código definido
na classe (variáveis e métodos) estará contido entre chaves.

//classe Olá: arquivo Olá.cs


class Olá
{
public static int main (string [ ] args)
{
//...
return 0;
}
}

O código-fonte de um programa em C# é armazenado normalmente em um ou mais arquivos de


texto com a extensão .cs, como o caso do arquivo Olá.cs.


mmFundamentos de programação – Algoritmos, estruturas de dados e objetos

G.1.1 Espaços de nomes


As classes relacionadas são agrupadas em espaços de nomes. O nome completo de uma classe é especificado
pelo espaço de nome seguido por um ponto e o nome de uma classe.
System.Console

Uma sentença using permite a uma classe ser referida somente por seu nome de classe.

G.1.2 Tipos de dados


Os tipos de dados em C# podem ser classificados em:
• Tipos valor.
• Tipos referência.
• Tipos ponteiro.

Tipos valor
Os tipos valor contêm diretamente seus dados. Cada variável de um tipo valor tem sua própria cópia dos dados.
Os tipos valor são atribuídos normalmente na pilha e são destruídos automaticamente quando a variável sai
do escopo.
Os tipos valor são: tipos estrutura e tipos enumeração.

Tipos referência
Os tipos referência não contêm diretamente dados, mas referências a dados. As variáveis de tipos referência
armazenam referências a dados denominados objetos. Duas variáveis diferentes podem referenciar o mesmo
objeto. Os tipos referência são atribuídos no montículo e eventualmente são destruídos por um processo
conhecido como coleta de lixo (garbage collection).
Os tipos referência são: string, object, tipos classe, tipos array, interfaces e delegados.

Tipos ponteiro
Os tipos ponteiro somente são utilizados em códigos pouco seguros (perigosos).

Tipos valor
Os tipos valor podem ser do tipo estrutura ou do tipo enumeração. O tipo estrutura engloba as estruturas
definidas pelo usuário e os tipos simples (Figura G.1).

Tabela G.1 Tipos simples predefinidos em C#

Palavra reservada em C# Estrutura em espaço de nome System


sbyte System.SByte
byte System.Byte
short System.Int16
ushort System.UInt16
int System.Int32
uint System.UInt32
long System.Int64
ulong System.UInt64
char System.Char
float System.Single
double System.Double
bool System.Boolean
decimal System.Decimal
Manual de sintaxe da linguagem C#mm

Tipos valor

Tipo estrutura Tipo enumeração

Estruturas definidas pelo usuário Tipos simples

Tipo numérico bool

Tipo integral Tipo ponto flutuante Tipo decimal

sbyte float
byte double
short
ushort
int
uint
long
ulong
char

Figura G.1 Classificação dos tipos valor.

G.1.3 Tipos inteiros


Os oito tipos inteiro de C# fazem parte dos denominados tipos integrais e têm as características refletidas na
Tabela G.2. O intervalo de cada um deles pode ser obtido consultando os campos constantes MaxValue e
MinValue das respectivas estruturas.

Tabela G.2 Tipos de dados inteiros em C#

Palavra reservada Tamanho Com sinal/Sem sinal Tipo na biblioteca de classes

sbyte 8 bits com sinal System.SByte


byte 8 bits sem sinal System.Byte
short 16 bits com sinal System.Int16
ushort 16 bits sem sinal System.UInt16
int 32 bits com sinal System.Int32
uint 32 bits sem sinal System.UInt32
long 64 bits com sinal System.Int64
ulong 64 bits sem sinal System.UInt64

Literais de tipo inteiro


Um literal é utilizado quando escrevemos explicitamente um valor em um programa. Um inteiro literal pode
ser um inteiro decimal ordinário ou um inteiro hexadecimal. A representação hexadecimal é precedida por
0x ou 0X. Por exemplo:

quadrosXadrez =64;
quadrosXadrez =0x40;
mmFundamentos de programação – Algoritmos, estruturas de dados e objetos

Os literais inteiros são armazenados sempre como valores de 32 ou 64 bits.

Sufixos nos literais


L (ou 1)......................................... para long
U (ou u)......................................... para “sem sinal” ..................................... Ex.: uint, ulong
UL (e variantes ul, LU etc.)......... para ulong

G.1.4 Tipos ponto flutuante


C# dispõe de dois tipos reais no ponto flutuante: float e double. O tipo float pode representar valores
com uma precisão de 7 dígitos, enquanto o tipo double pode fazê-lo com precisão de 15 ou 16 dígitos.

Tabela G.3 Tipos de dados em ponto flutuante em C#

Palavra reservada Tamanho Tipo na biblioteca de classes

float 32 bits System.Single


double 64 bits System.Double

Literais de ponto flutuante


São utilizados tanto em notação decimal como exponencial:
• Um literal de ponto flutuante sem sufixo é armazenado na memória como double.
• Para especificar um tipo float, é necessário utilizar o sufixo F ou f. Os sufixos D ou d indicam um
literal double.

G.1.5 Tipo decimal


O tipo decimal é um tipo de dado de 128 bits e até 28 dígitos decimais.

Tabela G.4 Tipo de dados decimal em C#

Palavra reservada Tamanho Tipo na biblioteca de classes

decimal 128 bits System.Decimal

Literais decimais
Um literal decimal é especificado com o sufixo M ou m.

G.1.6 Tipo caractere


Os caracteres são representados pelo tipo de dado char que se corresponde com um caractere Unicode.

Tabela G.5 Tipo de dados caractere em C#

Palavra reservada Tamanho Tipo na biblioteca de classes

char 16 bits System.Char


Manual de sintaxe da linguagem C#mm

Literais caractere
Um literal char representa um caractere único. Pode constar de um caractere entre aspas simples ou um ca-
ractere Unicode em hex (hexadecimal) com prefixos \x ou \u, ou um caractere de escape (para representar
algo semelhante a uma aspa ou barra inclinada), por exemplo:

‘V’ //caractere entre aspas


‘\x0056’ //caractere em hex
‘\u0056’ //igual a caractere em Unicode
‘\’’ //aspas simples

Tabela G.6 Caracteres de escape em C#

Caractere de escape Nome Valor

\’ aspa simples 0x0027


\” aspas duplas 0x0022
\\ barra inclinada inversa 0x005C
\0 nulo 0x0000
\a alarme 0x0007
\b retrocesso 0x0008
\f avanço de página 0x000C
\n nova linha 0x000A
\r retorno de carro sem avanço de linha 0x000D
\t tabulação horizontal 0x0009
\v tabulação vertical 0x000B

G.1.7 Tipo booleano


O tipo bool representa valores lógicos: verdade (true) ou falso (false).

Tabela G.7 Tipo de dados booleano C#

Palavra reservada Tamanho Tipo na biblioteca de classes

bool 8 bits System.Boolean

Literais booleanos
Os valores booleanos são true e false. Em C# as palavras reservadas true e false podem ser utilizadas
como um operador e como um literal.

G.1.8 Tipo estrutura


Uma estrutura (struct) é um tipo valor que pode agrupar tipos não-homogêneos. Pode ter também constru-
tores e métodos. As declarações struct podem aparecer nos mesmos lugares que as declarações de classes.

Declaração de uma estrutura


[atributos] [modificadores] struct Identificador [Interfaces]
corpo_estrutura

atributos
mmFundamentos de programação – Algoritmos, estruturas de dados e objetos

Um atributo é uma etiqueta que permite associar ao código informação adicional que se incorpora ao sistema
de metadados. Essa informação adicional estabelecida pelo programador pode ser extraída usando os serviços de
reflexão e ser utilizada para modificar a conduta em tempo de execução. Os atributos podem ser predefinidos e
definidos pelo usuário. A declaração de uma estrutura permite especificar mais de um atributo
modificadores
new
public
protected
internal
private

ou combinações válidas deles.


Interfaces
:lista_tipo_interfaces
corpo_estrutura
{
declarações_de_membros
}

Exemplo
No exemplo, em razão do atributo estabelecido, ao compilar será produzida uma mensagem indicando que se
trata de uma Estrutura antiquada.
using System;
[Obsoleto(“Estrutura antiquada”)] //atributo
public struct Vetor
{
public float endereço;
public int magnitude;
}

class TesteEstrutura
{
public static void main( )
{
Vetor [ ] vetores = new Vetor [200];
for (int i = 0; i < vetores.length; i++)
vetores[i] = new vetor( );
}
}

Um objeto estrutura é criado utilizando o operador new, mesmo que também possa ser criado sem utilizar
o mencionado operador. Quando não utilizamos o operador new, os campos não são inicializados por default
e o objeto não pode ser utilizado até que se inicializem seus campos.
Exemplo
using System;
public struct Endereço
{
public int número;
public string rua;
public void Mostrar ( )
{
Console.WriteLine(“Número: {0}, Rua: {1}”, número, rua);
}
}
Manual de sintaxe da linguagem C#mm

class TesteEstrutura
{
public static void main( )
{
Endereço e1, e2;
e1 = new Endereço( );
e1.número = 10;
e1.Mostrar( );
e2.número = 12;
e2.rua = “ ”;
e2.Mostrar( );
}
}

G.1.9 Tipos enumeração


Um tipo enumeração administra nomes alternativos para os valores de um tipo base subjacente. Esses nomes
alternativos são especificados mediante uma lista de identificadores válidos, constantes com nome, pelo pro-
gramador. As declarações enum podem aparecer nos mesmos lugares onde aparecem as declarações de classes.
Cada enumeração tem um tipo fundamental ou base que pode ser: byte, sbyte, short, ushort, int, uint,
long, ulong. Se não for especificado tipo, será utilizado int e, por default, ao primeiro membro enum se
atribui o valor 0, ao segundo membro, 1 etc. O valor associado aos membros de uma enumeração também
pode ser atribuído explicitamente.

Especificação de uma enumeração


[atributos] [modificadores] enum Identificador [base]
corpo_enumeração

base
:tipo_integral

corpo_enumeração
{
declarações_de_membros,
}

Exemplo 1
public enum Cor
{
Vermelho,
Verde,
Azul
}

Exemplo 2
//declara um enum de tipo long
public enum Cor : long
{
Vermelho,
Verde,
Azul
}
mmFundamentos de programação – Algoritmos, estruturas de dados e objetos

Exemplo 3
public enum EstadoReserva : byte
{
NãoExisteHotel, //0, implicitamente
ApartamentoDisponível, //1, implicitamente
Indicador = 5 //valor explícito
}

Exemplo 4
// Em c:\winnt\microsoft.net\framework\v1.0.3705\mscorlib.d1l
public enum System.IO.FileAccess
{
Read = 0x00000001,
ReadWrite = 0x00000003,
Write = 0x00000002,
}

G.1.10 Tipos referência


Uma variável de um tipo referência não contém diretamente seus dados, mas proporciona uma referência à
posição de memória onde eles se encontram armazenados. Os tipos referência são:

• Classes;
— Tipos classe.
— object.
— string.

• Array.
• Interface.
• Delegado.

Os tipos referência têm um valor nulo que indica a ausência de uma instância. As palavras reservadas que
permitem definir tipos referência são class, interface, delegate.

G.1.11 Classes
Uma classe é uma estrutura de dados que pode conter membros dados (constantes, campos e eventos), métodos,
construtores, destrutores, propriedades, indexadores, definições de operadores e tipos aninhados. Os tipos classe
suportam herança; mediante a herança, uma classe derivada pode ampliar ou especializar uma classe base.
Ao tratarmos as classes, temos de levar em conta que existem duas classes na biblioteca .NET Framework
que têm palavras reservadas como pseudônimo: object, string.

Definição de classes
Uma definição de uma classe consta de um cabeçalho e um corpo. O cabeçalho consta de palavras reservadas
e identificadores que representam: uma seqüência opcional de modificadores, a palavra reservada class, o
nome da classe, um nome opcional da classe pai, uma seqüência opcional de interfaces e o corpo da classe
com seus membros.

[atributos] [modificadores] class Identificador [: lista_base]


corpo_da_classe
Manual de sintaxe da linguagem C#mm

Os modificadores podem ser: new, abstract, sealed, public, protected, interna1 e private.
new somente é permitido em classes aninhadas.
public, protected, interl e private controlam a acessibilidade.
abstract é utilizado para indicar uma classe abstrata.
sealed, para evitar a derivação de uma classe.

lista_base

Lista com uma classe base como máximo (classe pai) e todas as interfaces implementadas separadas
por vírgulas.
Exemplo
public class MinhaClasse
{
protected int var;
void Procedimento1 (string Param)
{
//...
}
}

Modificadores de acesso
C# proporciona modificadores protected e internal, somente um modificador de acesso pode ser aplicado
a um membro ou tipo. A Tabela G.8 proporciona um resumo dos modificadores.

Tabela G.8 Significado dos modificadores de acesso

Modificador de acesso Descrição

public Declara um tipo ou membro visível a todos os programas. É a acessibilidade por default
para os membros de enumerações e interfaces.
internal Declara um tipo ou membro acessível só dentro da montagem a que pertence. É a
acessibilidade por default para todos os tipos não aninhados e pode ser omitida.
protected Declara o membro de uma determinada classe unicamente acessível dessa classe e suas
classes derivadas.
private Declara a um membro apenas visível em sua unidade de compilação. É a acessibilidade por
default para os membros de classes e estruturas.

Classes abstratas
Uma classe abstrata é diferenciada de uma classe não-abstrata em:

• Uma classe abstrata não pode ser instanciada diretamente e é um erro utilizar o operador new em uma
classe abstrata. Está projetada para ser classe base na herança.
• Uma classe abstrata pode conter membros abstratos.
• Uma classe abstrata não pode ser marcada (sealed).

Exemplo
public abstract class Base
{
public abstract void Abstrato( );
public void NãoAbstrato( )
10mmFundamentos de programação – Algoritmos, estruturas de dados e objetos

{
//Implementação
}
}
public abstract class DerivadaBase: Base
{
public abstract void OutroAbstrato( );
}
public class Derivada: DerivadaBase
{
public override void Abstrato( )
{
//Implementação
}
public override void OutroAbstrato( )
//Implementação
}
}

Classes marcadas
O modificador sealed assegura que uma classe nunca pode ser utilizada como classe base. Portanto,
os membros de uma classe sealed não podem ser declarados protected ou protected interna1.
Um exemplo de classe marcada da biblioteca de classes .NET Framework é a classe Math.

public sealed class Math

Herança
A herança significa que a classe derivada contém implicitamente todos os membros de sua classe base direta,
exceto construtores e destrutores. A herança facilita a reutilização de código, já que, de forma automática, o
código da classe base se põe à disposição da classe derivada. Todas as classes em C# herdam ou derivam, em
última instância, de uma classe base comum object.

Tipo de herança
C# somente suporta herança simples.

Especificação
[atributos] [modificadores] class IdentificadorClasseDerivada : ClasseBase
[,lista_interfaces]
corpo_da_classe

Exemplo
class BaseDados
{
//...
}
class SQLServer: BaseDados
{
//...
}
class DB2: BaseDados
{
//...
}
Manual de sintaxe da linguagem C#mm11

G.1.12 Métodos
Uma classe encapsula dados e comportamentos em uma única entidade. Um método é um membro que
implementa um cálculo ou ação que pode ser executado por um objeto ou classe.

Declaração de métodos
As declarações de métodos constam de um cabeçalho e um corpo. No cabeçalho devem ser especificados um
tipo de retorno, um identificador e uma lista de argumentos (parâmetros). O tipo de retorno pode ser qualquer
tipo (incluindo uma classe) ou o tipo void se não for devolvido nada por meio do nome do método. A lista
de argumentos pode estar vazia. Os métodos podem também ter uma visibilidade explícita.

[atributos] [modificadoresDeMétodos] tipoDeRetorno NomeMétodo


([lista_parâmetros_formais])
corpo_do_método

Os modificadoresDeMétodos podem ser:

new virtual
public sealed
protected override
internal abstract
private extern
static

e o método pode não ter nenhum ou deve ter uma combinação válida deles, o que implica que:
• A declaração não inclui o mesmo modificador várias vezes.
• A declaração inclui como máximo um dos seguintes modificadores: static, virtual e override.
• A declaração inclui como máximo um dos seguintes modificadores: new ou override.
• Se a declaração inclui o modificador abstract, não inclui os modificadores static, virtual nem
extern.
• Se a declaração inclui o modificador private, então não inclui virtual, override nem abstract.
• Se a declaração inclui o modificador sealed, então também inclui o modificador override.

O tipoDeRetorno especifica o tipo de valor calculado e devolvido pelo método e pode ser
tipo
void

Na implementação do método, quando ele não tiver sido declarado void, será utilizada a instrução return
para devolver um valor ao ponto da ativação do método.
A lista_parâmetros_formais especifica os parâmetros do método. O nome do método e o tipo e o
número dos parâmetros formais definem a assinatura do método. Nem o tipo de retorno nem os nomes dos
parâmetros formam parte da assinatura. A assinatura de um método deve ser diferente das assinaturas de outros
métodos declarados na mesma classe. Especificamente, a assinatura de um método consta de nome e número,
modificadores e tipo de seus parâmetros formais.
O corpo_do_método pode ser um bloco_de_sentenças ou um ;. Assim, quando o método for
abstract ou extern, o corpo consta simplesmente de um ponto-e-vírgula, ao passo que os casos restantes
constam de um bloco que especifica as sentenças a serem executadas quando invocamos o método.
Exemplo
abstract class Conta
{
protected abstract void Depositar(double quantidade);
}
12mmFundamentos de programação – Algoritmos, estruturas de dados e objetos

class ContaCorrente: Conta


{
protected sealed override void Depositar (double quantidade)
{
}
}

Parâmetros dos métodos


Os parâmetros de um método, se existem, são declarados na lista de parâmetros formais do método. Os parâme-
tros formais de um método são os parâmetros de cabeçalho do método. Os parâmetros reais de um método são
as expressões entre vírgulas na lista de parâmetros da ativação do método. Existem quatro tipos de parâmetros
formais:

1. Parâmetros valor (são declarados sem modificadores).


2. Parâmetros referência (são declarados com o modificador ref).
3. Parâmetros de saída (são declarados com o modificador out).
4. Parâmetros array (são declarados com o modificador params).
Exemplo
class Somar
{
public static int SomaNúmeros(int x, int y)
//x e y são os parâmetros formais
{
return x + y;
}

public static void Main( )


{
int Soma = SomaNúmeros (5, 8);
//5 e 8 são os parâmetros reais
System.Console.WriteLine(Soma);
}
}

Ativação de métodos
Quando ativamos um método, devemos proporcionar os argumentos do tipo adequado. A ativação ou
invocação de um método pode ser realizada de duas maneiras, dependendo de se o método devolve ou
não um valor. Assim, quando o método devolve um valor, a ativação do método é tratada como um valor,
mas se o método devolve void, uma ativação do método deve ser uma sentença.

// interior de um método
{
int Soma = SomaNúmeros(5, 8);
//...
}

Parâmetros valor
O modo por default de passagem de parâmetros em C# é a ativação por valor, na qual os valores dos parâmetros
reais são copiados na área de armazenamento dos parâmetros formais. Devemos levar em conta que as variáveis
que passam como parâmetros podem ser do tipo valor ou do tipo referência. Uma variável de tipo referência
não contém os dados diretamente, mas uma referência ao lugar onde são armazenados; isso implica que, quando
passamos por valor uma variável de tipo referência, é possível devolver mudados os dados apontadores pela
referência, mas não o valor da própria referência.
Manual de sintaxe da linguagem C#mm13

Parâmetros referência
Um parâmetro declarado com um modificador ref é um parâmetro referência e, ao contrário de um parâmetro
valor, não cria uma nova posição de armazenamento.
Exemplo 1
class Teste1
{
static void Intercâmbio(ref int x, ref int y)
{
int aux = x;
x = y;
y = aux
}

public static void Main( )


{
int i = 1, j = 5;
Intercâmbio (ref i, ref j);
System.Console.WriteLine (“i={0}, j={1}”, i , j);
}
}
Exemplo 2
class Teste2
{
static void Calcula(int x, int y, ref int soma,
ref int produto)
{
soma = x+y;
produto = x*y;
}
public static void Main ( )
{
int s = 0, p = 0;
int i = 1, j = 5;
Calcula (i, j, ref s, ref p);
System.Console.WriteLine(“{0}+{1}={2}, {0}*{1}={3}”,
i, j, s, p);
}
}

Parâmetros de saída
Um parâmetro referência está projetado realmente como um meio de comunicação bidirecional entre o pro-
grama ativador e o programa ativado. Um parâmetro declarado com um modificador out é um parâmetro de
saída. De forma semelhante em um parâmetro referência, um parâmetro de saída não cria uma nova posição
de armazenamento, ao contrário, representa a mesma posição de armazenamento que a variável dada como
argumento, na invocação do método.
Quando um parâmetro formal é um parâmetro de saída, o argumento correspondente em uma invocação
do método deve constar da palavra reservada out seguida por uma variável do mesmo tipo que o parâmetro
formal.
Os parâmetros referência devem ser inicializados antes de seu uso; pelo contrário, não é necessário atribuir
valor a uma variável antes que se possa passar como um parâmetro de saída. No interior de um método, como
uma variável local, um parâmetro de saída é considerado inicialmente não atribuído e devemos atribuí-lo
antes que seu valor seja utilizado. Os parâmetros de saída são utilizados normalmente em métodos que pro-
duzem múltiplos valores de retorno.
14mmFundamentos de programação – Algoritmos, estruturas de dados e objetos

Exemplo
class Teste3
{
static void DividirCaminho(string caminho, out string rota, out string
nome)
{
int i = caminho.Length;
while (i>0)
{
char car = caminho [i-1];
if (( car == ‘\\’) || (car == ‘/’) || (car == ‘:’ ))
break;
i--;
}
rota = caminho.Substring(0,i);
nome = caminho.Substring(i);
}
public static void Main ( )
{
string c, n;
DividirCaminho (“C :\\livro\\Tema01\\Bem-vindo.cs”,
out c, out n);
System.Console.WriteLine(c);
System.Console.WriteLine(n);
}
}

Parâmetros array
Um parâmetro declarado com um modificador params é um parâmetro array. Se uma lista de parâmetros
formais inclui um array parâmetro, deve ser o último parâmetro da lista e deve ser um tipo array de uma só
dimensão. Não podemos combinar o modificador params com os modificadores ref e out.
Exceto por permitir um número variável de argumentos em uma invocação, um parâmetro tipo array é
equivalente a um parâmetro valor.
Exemplo
using System;
class Teste4
{
static void F (params int [ ] args)
{
Console.WriteLine(“O array contém {0} elementos: ”, args.Length);
foreach (int i in args)
Console.Write(“{0} ”, i);
Console.WriteLine( );
}
public static void Main( )
{
int [ ] a ={1,2,3};
F(a);
F(15,25,35,40);
F( );
}
}
Manual de sintaxe da linguagem C#mm15

G.1.13 Sobrecarga de métodos


A sobrecarga de métodos permite que o programador de C# utilize o mesmo nome do método em múltiplas
ocasiões com argumentos diferentes em cada caso.
Em C# podemos sobrecarregar os nomes dos métodos, ou seja, considerar que dois métodos têm nomes
diferentes se têm diferentes assinaturas. Dois métodos têm a mesma assinatura se têm o mesmo nome e o
mesmo número de parâmetros, e os parâmetros têm os mesmos tipos de dados e os mesmos modificadores
(nenhum, ref, out).

Exemplo
using System;
class Teste5
{
/*
O método EncontrarMax se sobrecarrega para
parâmetros long ou string
*/

static string EncontrarMax(string a, string b)


{
return String.Compare(a, b) <= 0 ? b : a;
}
static long EncontrarMax(long a, long b)
{
return a < b ? b : a;
}
public static void Main( )
{
Console.WriteLine(EncontrarMax(“Ana”, “Anastácia”));
Console.WriteLine(EncontrarMax(3,9L));
}
}

G.1.14 Sobrecarga de operadores


A sobrecarga de operadores é a propriedade que permite a um operador atuar de maneira diferente segundo o
tipo de operando que seja aplicado. A sobrecarga é uma redefinição da função que o operador efetua. Para
redefinir um operador, utilizamos a seguinte sintaxe:

 public static valorRetorno operator operador (tipo p1[, tipo p2])

Todos os métodos Valor devolvido Operador sobrecarregado Parâmetros passados,


sobrecarregados devem ser passados
devem definir-se como por valor
public e static

Tabela G.9 Operadores unitários e binários que se podem sobrecarregar

Tipo Operadores

Unitários + – ! ~ + + – true false


Binários + – * / % & |   ^ << >> == != < > <= >=
16mmFundamentos de programação – Algoritmos, estruturas de dados e objetos

Exemplos
public static Empréstimo operator + (Empréstimo p1, Empréstimo p2)
public static Relógio operator + (Relógio c1, Relógio c2)
public static Relógio operator + (Relógio c1, int h2)

G.1.15 Interfaces
Uma interface define um contrato, e uma classe ou estrutura que implementa uma interface deve cumprir seu
contrato. As interfaces podem conter métodos, propriedades, indexadores e eventos e a classe que implemente
a interface tem de definir todos e cada um dos elementos dessa interface ou o código não será compilado. As
interfaces, como as classes, são tipos referência. A grande diferença é que não existe código de implementação
em uma interface.
[atributos] [modificadores] interface Identificador
[: ListaDeInterfacesBase]
corpo_interface

Os modificadores podem ser:


• new para interfaces aninhadas.
• public, protected, internal e private controlam a acessibilidade.
• Identificador. Costuma-se adotar como convenção que os nomes das interfaces comecem com a letra I.
• ListaDeInterfacesBase. Uma interface pode herdar de zero ou mais interfaces.
• corpo_interface. Define os membros da interface.
{
declarações_de_membros_da_interface
}

Membros de uma interface


Uma declaração de uma interface pode ter zero ou mais membros. Os membros de uma interface devem ser
métodos, propriedades, eventos ou indexadores.
Uma interface não pode conter constantes, campos, operadores, construtores, destrutores ou tipos, nem
pode conter membros estáticos de nenhum tipo.
Todos os membros da interface têm implicitamente acesso público.
Exemplo
using System;
interface IConta
{
void Depositar(decimal conta);
void Retirar(decimal conta);
decimal Salário{get};
string Proprietário{get; set;}
int Id{get}
}

Herança de interfaces
As interfaces podem herdar de outras interfaces (contrariamente ao que acontece nas classes, em que existem
somente heranças simples) se existem heranças múltiplas de interface.
Exemplo
using System;
interface IConta: IContaCorrente, IContaCrédito
{
}
Manual de sintaxe da linguagem C#mm17

G.1.16 Delegados
Os delegados são tipos referência que podem manter referências a métodos que se correspondam com sua
assinatura e resultam semelhantes aos ponteiros a funções presentes em outras linguagens, tais como Pascal,
C++ etc.
Entretanto, contrariamente aos ponteiros, os delegados são totalmente orientados a objetos e apontam
sempre um método válido. Contrariamente aos ponteiros, as funções membro encapsulam tanto a instância do
objeto como um método.

[atributos] [modificadores] delegate tipoResultado Identificador


(lista_de_parâmetros_formais);

Os modificadores podem ser: new, public, protected, internal, private.

G.2 SENTENÇAS

Em C# as sentenças podem ser simples ou estruturadas, além do que é possível agrupar várias sentenças em
um bloco.

G.2.1 Bloco
Um bloco consta de uma lista de sentenças opcionais entre chaves. Omitindo a lista de sentenças, dizemos que
o bloco é vazio.
Exemplo
if (x < y)
{
int aux = x;
x = y;
y = aux;
}

G.2.2 Sentença vazia


A sentença vazia não faz nada e é utilizada quando não existem operações a ser executadas em um contexto
que requer uma sentença.
Sintaxe

G.2.3 Sentença etiquetada


Etiquetar uma sentença consiste em colocar uma etiqueta. Uma instrução etiquetada declara uma etiqueta com
o nome dado pelo identificador. O escopo da etiqueta é o bloco em que a etiqueta foi declarada e qualquer
bloco aninhado.
Sintaxe
identifier : sentença;
Exemplos
// permitido
if (T (x))
{
18mmFundamentos de programação – Algoritmos, estruturas de dados e objetos

if (x >= 0)
goto x;
x=-x;
x: return x;
}

/* Não é permitido. A declaração da etiqueta não pode ser encontrada em uma


sentença aninhada naquela da qual foi ativada
*/
if (!T(x))
goto x;
else
if (x < 0)
x: x=-x;

Uma etiqueta só pode ser referenciada de sentenças goto dentro do escopo da etiqueta.

G.2.4 Estruturas de controle


As sentenças que permitem controlar o fluxo em uma aplicação C# são divididas em três categorias: sentenças
condicionais, iterativas e salto.

G.2.5 Sentenças de seleção (condicionais)


Selecionam as sentenças a serem executadas segundo o valor de uma expressão de controle.

Sentença if

As sentenças if proporcionam controle sobre duas alternativas baseadas no valor lógico de uma expressão.

1) if (expressãoLógica)
sentença1;
else
sentença2;
sentença3;

Se a expressão avaliada for verdadeira, executa-se a sentença1 (bifurcação verdadeira). Se a expressão


avaliada for falsa, será executada a sentença2 (bifurcação falsa). Em qualquer um dos casos, será executada
a sentença3.
Exemplo
if (i < 0)
System.Console.WriteLine(“Número negativo”);
else
System.Console.Write(“Número positivo”);

2) if (expressãoLógica)
sentença1;
sentença2;

Se a expressão for verdadeira, será executada a sentença1 seguida pela sentença2. Se a expressão for
avaliada falsa, será executada a sentença2 diretamente.
Manual de sintaxe da linguagem C#mm19

3) if (expressãoLógica)
bloco
else
bloco
sentença3;
4) if (expressãoLógica)
bloco
sentença2;

G.2.6 Sentença switch


A sentença switch executa as sentenças que estão associadas ao valor da expressão de controle.

switch (expressão)
{
case constante1:
sentenças1;
sentença_salto; // break, continue, goto ou return
case constante2:
sentenças2:
sentença_salto;
...
default
sentençasX;
sentença_salto;
}

Avalia-se a expressão e o resultado é comparado com cada uma das expressões constantes definidas nas
diferentes sentenças case. Uma vez encontrada uma coincidência, o controle é passado à primeira linha de
código nessa sentença case.
Exemplo
using System;
public class DemoSwitch
{
public static void Main (string[ ] args)
{
for (int i=0; i<args.Length; i++)
{
switch (args [i])
{
case “1”;
Console.Write(“Baixo”);
break;
case “2”;
Console.Write(“Médio”);
goto case “1”;
case “3”;
Console.Write(“Médio”);
goto case “4”;
case “4”;
Console.Write(“Alto”);
break;
case “5”;
20mmFundamentos de programação – Algoritmos, estruturas de dados e objetos

case “6”;
Console.Write(“Superior”);
break;
default:
Console.Write(“Caso especial”);
break;
}
Console.WriteLine( );
}
}
}

Execução
C:\livro\Tema07>DemoSwitch 1 2 3 4 5 6 7
Baixo
Médio Baixo
Médio Alto
Alto
Superior
Superior
Caso especial

G.2.7 Laços
Um laço permite executar repetidamente uma série de ações. As sentenças repetitivas ou de iteração são:
while, do, for e foreach.

Sentença while
A sentença while executa condicionalmente zero ou mais vezes as sentenças fechadas no laço.

while (expressãoLógica)
blocoSentenças
sentença;

Se a expressão for verdadeira, é executado o blocoSentenças do interior do laço. Se a expressão for


falsa, serão executadas as sentenças fora do laço.
Exemplo
while (conta <= número)
{
System.Console Write(conta)
if (conta < número)
System.Console.Write(“, ”);
conta++;
}

Sentença do
A sentença do executa condicionalmente uma série de sentenças uma ou mais vezes. O corpo do laço é
executado pelo menos uma vez. O corpo do laço pode constar de somente uma sentença.

do
sentença1; //a sentença é executada pelo menos uma vez
while (expressãoLógica);
Manual de sintaxe da linguagem C#mm21

ou de mais de uma sentença


do
{
listas_de_sentenças
}
while (expressãoLógica);

Se a expressão for verdadeira, o laço será executado uma vez mais e termina a execução quando a expressão
for falsa.
Exemplo
do
{
System.Console.Write(conta);
if (conta < número)
System.Console.Write(“, ”);
conta++;
}
while (conta <= número);

Sentença for
A sentença for avalia uma seqüência de expressões de inicialização e, a seguir, enquanto a condição for
verdadeira, executam as sentenças do interior do laço e termina a execução quando a expressão controle
for falsa:
for (inicialização; condição_de_terminação; iterador)
sentença;
for (inicialização, condição_de_terminação; iterador)
bloco

Essencialmente, o laço for inicializa a(s) variável(is) de controle mediante a(s) sentença(s) de atribuição
especificadas na sessão de inicialização e depois verifica se a condição_de_terminação é verdadeira.
Se a condição é verdadeira, são executadas as sentenças do interior do laço, e se a condição é falsa, saltam-se
todas as sentenças do interior do laço; ou seja, não são executadas. Quando a condição é verdadeira, o laço
executa uma iteração (todas suas sentenças) e a seguir a(s) variável(is) de controle do laço será(ão) incrementada(s)
ou decrementada(s) na forma especificada mediante o iterador. Cada uma das partes (inicialização;
condição_de_terminação; iterador) é opcional.

Exemplos
1) int soma = 0;
for (int i=1; i<=10; i++)
soma += i;
Console.WriteLine (soma);
2) for (int i = 1; i < 16; i=i*2)
Console WriteLine(i);
3) for (int i=1, j=1, j<=5 ; i++)
{
Console.WriteLine(“{0} {1}”,j, i);
if (i==3)
{
i=0;
j++;
}
}
4) for (;;) ; // laço infinito com sentença vazia
22mmFundamentos de programação – Algoritmos, estruturas de dados e objetos

A sentença foreach
A sentença foreach enumera os elementos de uma coleção, executando a(s) sentença(s) embutida(s) para
cada elemento da coleção. A instrução foreach não deve ser usada para mudar o conteúdo de uma coleção.

foreach (tipo identificador in coleção)


{
lista_sentenças
}

Exemplo
int [ ] primos = {2, 3, 5, 7, 11, 13};
int soma = 0;
foreach (int primo in primos)
{
Console”Write(“{0} ”, primo);
soma +=primo;
}
Console.WriteLine(“\r\n {0}”, soma);

G.2.8 Sentenças de salto


As sentenças de salto transferem o controle do programa incondicionalmente. Existem as seguintes:

break, continue, goto, return.

Sentença break
A sentença break é utilizada para terminar o laço atual ou a sentença switch na qual aparece. O controle é
passado a seguir da linha do código que segue a última sentença interna do laço ou sentença switch.

Sintaxe
break;

Exemplo
for (int i = 1; i <= 100; i++)
{
if (0 == i % 4)
Console.WriteLine(i);
if (i == 66)
break;
}

Uma aplicação interessante de break é sair de laços infinitos. O método é criar um laço infinito no qual
o controle será transferido fora do laço somente quando alcançamos uma sentença break.

Sentença continue
A sentença continue começa uma nova iteração do laço (while, do, for ou foreach) mais perto.
Ao contrário da sentença break, continue não produz uma saída completa do laço, somente termina a
iteração em curso e começa a seguinte iteração.

Sintaxe
continue;
Manual de sintaxe da linguagem C#mm23

Sentença goto
A sentença goto somente deve ser utilizada em circunstâncias muito excepcionais. Seu uso costuma pressupor
uma má prática de programação.
goto transfere o controle a uma sentença marcada por uma etiqueta.
Sintaxe
goto identificador;
goto case expressão_constante;
goto default;

Sentença return
A sentença return devolve o controle e o valor da expressão_retorno ao invocador da função membro
na qual aparece a sentença return. Se um método é do tipo void, a sentença return pode aparecer sem
incluir expressão_retorno ou ser omitida.
Sintaxe
return [expressão_retorno];

G.2.9 Sentenças de manuseio de exceções


As exceções são utilizadas para informar sobre os possíveis erros que podem ser produzidos durante a execu-
ção de um programa e efetuar seu tratamento. O manuseio de exceções é realizado mediante as sentenças:
try-catch, try-finally, try-catch-finally e throw.

Sentenças try
A instrução try-catch consiste em um bloco de teste seguido por uma ou mais cláusulas de captura que
especificam os administradores para as exceções diferentes.
O bloco finally permite limpar qualquer recurso assinado no bloco try. O controle passa sempre à
cláusula finally sem ter em conta como é efetuada a saída do bloco try, ou seja, tanto se produz uma
exceção e se captura, como não se captura, como se não fosse produzida a exceção, como se sai do bloco
try e com return break continue finally poderia aparecer depois de um bloco try sem cláusulas
catch (instrução try-finally) ou ao final das cláusulas catch do bloco try (instrução try-catch-
finally).
Sintaxes
try bloco_try cláusulas_catch
try bloco_try finally bloco_finally
try bloco_try cláusulas_catch finally bloco_finally

As cláusulas_catch serão

cláusulas_catch_específicas [cláusula_catch_geral]

ou

[cláusulas_catch_específicas] cláusula_catch_geral

As cláusulas catch específicas poderão ser de diferentes tipos.


catch (declaração_exceção)
bloco_catch
catch (tipo_exceção)
bloco_catch
24mmFundamentos de programação – Algoritmos, estruturas de dados e objetos

A cláusula catch geralmente terá o formato seguinte:


catch
bloco_catch

Sentença throw
Uma sentença throw lança uma exceção:
Sintaxe
throw [expressão];

Uma sentença throw com uma expressão lança a exceção produzida avaliando a expressão. A expressão
deve representar um valor de tipo classe System.Exception ou de um tipo classe derivado de System.
Exception. Uma sentença throw sem expressão pode ser utilizada somente em um bloco catch, lançando
novamente a exceção que está sendo manipulada pelo bloco catch.

G.2.10 Sentenças checked e unchecked


A palavra reservada checked ativa a geração de exceções em tempo de execução diante de transbordamentos
em operações aritméticas e conversões quando trabalhamos com tipos integrais. Pode ser utilizada como
operador e como sentença. Quando usamos como sentença sua sintaxe é:
checked bloco

A palavra reservada unchecked desativa a geração de exceções em tempo de compilação diante de


transbordamentos em operações aritméticas e conversões quando trabalhamos com tipos integrais. Pode ser
utilizada como operador e como sentença. Quando usamos como sentença sua sintaxe é:

unchecked bloco

G.2.11 Sentença lock


Em programação multilinha, a marca das sessões críticas pode ser efetuada por meio da instrução lock, que
estabelece a exclusão mútua entre fios para o acesso aos dados protegidos por esta instrução. A palavra reser-
vada lock marca um bloco como sessão crítica.
Sintaxe
lock (expressão) bloco

G.2.12 Sentença using


A palavra reservada using proporciona três tipos de serviços:
• Como diretiva:
— Criar um pseudônimo para um espaço de nome.
— Permitir que possam ser usados os tipos de um espaço de nome sem necessidade de qualificação.
• Como sentença:
— Estabelecer o escopo de um objeto e onde deva ser liberado. A instrução using obtém um ou mais
recursos, executa uma instrução e libera o recurso. Seu formato é:
using ( aquisição_objeto_que_implementa_IDisposable )
{
sentença;
}
Manual de sintaxe da linguagem C#mm25

G.3 OPERADORES E EXPRESSÕES


Um operador é um símbolo que indica uma operação que será realizada sobre um ou mais parâmetros.
Esta operação produzirá um resultado. Os operadores de C# seguem as regras e notações básicas. Os valores
sobre os quais operam chamam-se operandos.

G.3.1 Operadores aritméticos


Tabela G.10 Operadores aritméticos

Símbolo Descrição

+ Operador unário + ou soma


- Operador unário – (só trabalha com tipos que admitem valores negativos) ou subtração
* Multiplicação
/ Divisão inteira
/ Divisão real
% Módulo

G.3.2 Operadores relacionais


Os operadores relacionais geram um resultado booleano.

Tabela G.11 Operadores relacionais

Símbolo Descrição Exemplo Resultado do exemplo

== Igual (operador formado por dois sinais = consecutivos ) 8 == 2 false


!= Distinto 8 != 2 true
> Maior que 8 > 2 true
< Menor que 8 < 2 false
>= Maior ou igual 8 >= 8 true
<= Menor ou igual 8 <= 8 true

G.3.3 Operadores lógicos condicionais

Tabela G.12 Operadores lógicos

Símbolo Descrição

& AND binário lógico


&& AND binário em curto-circuito
| OR binário lógico
|| OR binário em curto-circuito
! NOT unário lógico
^ XOR binário

Tabela G.13 Tabela real de AND

x y x AND y
false false false
false true false
true false false
true true true
26mmFundamentos de programação – Algoritmos, estruturas de dados e objetos

Tabela G.14 Tabela real de OR

x y x OR y
false false false
false true true
true false true
true true true

Tabela G.15 Tabela real de NOT

x NOT x

false true
true false

Tabela G.16 Tabela real de XOR

x y x XOR y
false false false
false true true
true false true
true true false

G.3.4 Operador ternário condicional


O operador condicional ?: é um operador ternário. O formato do operador condicional é:

expressão1 ? expressão2 : expressão3;

A expressão lógica (expressão1) é avaliada em primeiro lugar. Avaliando-se true, a expressão global
recebe o valor expressão2, em caso contrário, o valor expressão3.

G.3.5 Operadores de manipulação de bits


C# tem um número determinado de operadores bit a bit (bitwise) que podem ser utilizados para manipulação
de bits. Existem dois tipos de operações de manipulação de bits:

• Lógicos bit a bit: AND, OR, XOR (or exclusive) e NOT, às vezes denominados operadores de máscara.
• Operadores de deslocamento: deslocamento para a direita e deslocamento para a esquerda.

Tabela G.17 Operadores de manipulação de bits

Símbolo Descrição

~ NOT bit a bit


& AND bit a bit
| OR bit a bit
^ XOR bit a bit
<< Deslocamento para a esquerda
>> Deslocamento para a direita
Manual de sintaxe da linguagem C#mm27

Operadores de deslocamento
a = b << n // desloca n posições para a esquerda
// equivale a multiplicar por 2 n vezes
a = b >> n // desloca n posições para a direita e
// estende o sinal equivalente a dividir
// por 2 n vezes

G.3.6 Operadores de atribuição


Os operadores de atribuição atribuem um novo valor a uma variável, uma propriedade ou um elemento
indexado.
Sintaxe
variable operador_atribuição expressão

Tabela G.18 Operadores de atribuição

Símbolo Descrição

= Atribuição simples
+ + Incremento e atribuição
– – Decremento e atribuição
* = Multiplicação e atribuição
/ = Divisão e atribuição
% = Módulo e atribuição
+ = Soma e atribuição
- = Subtração e atribuição
<<= Deslocamento para a esquerda e atribuição
>>= Deslocamento para a direita e atribuição
& = Atribuição AND ou AND sobre bits e atribuição
| = Atribuição OR ou OR sobre bits e atribuição
^ = Atribuição XOR ou XOR sobre bits e atribuição

Operadores de atribuição simples


O operador = é utilizado para atribuir um valor a uma variável.
Sintaxe
variable = expression

Exemplo
int x = (y = + + z) + 50;

Atribuição composta
Uma atribuição composta realiza uma operação binária como parte da atribuição.

Tabela G.19 Operadores de atribuição composta

Descrição Operadores

Aritméticos += -= *= /= %= ++ --
Deslocamento <<= >>=
Bit a bit &= |= ^=
Lógicos &= |= ^=
28mmFundamentos de programação – Algoritmos, estruturas de dados e objetos

G.3.7 Expressões
As expressões são construídas combinando constantes e variáveis. Quando as expressões são avaliadas, o
compilador de C# segue regras de precedência ou prioridade para determinar a ordem das operações a serem
realizadas. Quando um operando está entre dois operadores com o mesmo nível de precedência ou prioridade,
a associatividade do operador controla a ordem de avaliação. A maioria dos operadores se associa da esquerda
para a direita.
Tabela G.20 Prioridade dos operadores em C#

Primários (x) x.y -> f(x) a[x] x++ x-- new stackallock typeof sizeof
checked unchecked
Unários + - ~ ! ++x --x (tipo)x * & true false
Multiplicativos * / %
Aditivos + -
Deslocamento >> <<
Relacionais > >= < <= is as
Igualdade == !=
AND bit a bit &
XOR bit a bit ^
OR bit a bit |
AND em
curto circuito &&
OR em
curto circuito ||
Condicional ? :
Atribuição = *= /= %= += -= >>= <<= &= ^= |=

G.4 EXCEÇÕES
As exceções são objetos que descrevem e permitem controlar erros e problemas inesperados no funcionamento
de um programa. As exceções em C# proporcionam um meio estruturado uniforme e seguro de tipos para
manusear condições de erro na aplicação e no sistema.

G.4.1 Regras importantes de exceções em C#


Todas as exceções devem ser representadas por uma instância de um tipo classe derivada de System.
Exception.
Um bloco finally pode ser utilizado para escrever o código de terminação que será executado em
condições de execução normal e em condições excepcionais.
As exceções em nível de sistemas, tais como transbordamento, divisão por zero e referências nulas, têm
classes de exceções bem definidas.

G.4.2 Manuseio de exceções


O uso de exceções é realizado mediante as sentenças try, catch, throw e finally. O mecanismo de exceções
é utilizado para informar e manejar os erros. Informa-se um erro lançando uma exceção. O erro é manuseado
capturando a exceção. O mecanismo de exceções implica os seguintes elementos:
• O código que pode encontrar uma exceção deve estar dentro de um bloco try.
• As exceções são capturadas em um bloco catch.
• Um objeto Exception passa como parâmetro a catch.
• Podemos ter múltiplos blocos catch.
• Uma última cláusula finally contém o código que será executado conforme seja encontrada ou não
uma exceção.
• No método ativado, levantamos uma exceção por meio de uma sentença throw.
Manual de sintaxe da linguagem C#mm29

G.4.3 Lançar uma exceção


O lançamento de uma exceção cria um objeto exceção do tipo System.Exception ou uma classe derivada.
Sintaxe
throw [expressão];

Exemplo
using System;
class LançaExceção
{
public static void Main( )
{
try
{
//aconteceu algum erro
throw new AplicationException( );
}
catch (System.Exception e)
{
System.Console.WriteLine(e.Message);
}
}
}

G.4.4 Capturar uma exceção


Quando acontece uma exceção, o sistema busca a cláusula catch mais próxima que possa manejar a exceção,
que está determinada pelo tipo de exceção, em tempo de execução. A palavra catch define um bloco do
código cuja função é processar uma exceção de um tipo dado quando esta se captura. O código deste bloco é
chamado manipulador de exceção.
Sintaxe
try bloco_try cláusulas_catch

As cláusulas_catch serão:
cláusulas_catch_específicas [cláusula_catch_geral]
ou
[cláusulas_catch_específicas] cláusula_catch_geral
//catch específica
catch(TipoExceção parâmetro)
{
//ações
}
//catch específica
catch(TipoExceção)
{
//ações
}
//catch geral
catch
{
//ações
}
30mmFundamentos de programação – Algoritmos, estruturas de dados e objetos

Relançar uma exceção


Há ocasiões em que é necessário voltar a lançar uma exceção. Essa tarefa será realizada do bloco catch
mediante a palavra reservada throw.

G.4.5 Cláusula finally


No manuseio de exceções, é importante assegurar que um fragmento de código seja executado independente
da forma em que saia do bloco try e de caso se produza e capture ou não uma exceção. O bloco finally
resolve este problema e, mesmo que seja opcional, se está presente deve aparecer imediatamente depois dos
manipuladores catch. Garantimos que o código do bloco finally será executado sempre antes que o
método implicado termine.
Exemplo
using System;
class TesteBlocoFinally
{
public static void Main( )
{
try
{
Random r = new Random( );
int n = r.Next (2);
// r.Next( ) devolve um número aleatório entre 0 e 1
if (n == 1)
throw new ApplicationException(“Exceção gerada aleatoriamente”);
}
catch (Exception e)
{
Console.WriteLine (e.Message);
}
finally
{
Console.WriteLine(“Bloco finally”);
}
}
}