Escolar Documentos
Profissional Documentos
Cultura Documentos
básicos do
desenvolvimento
de software
Conceitos básicos do
desenvolvimento de
software, exame 98-361
Créditos
EDITOR Bryan Gambrel
DIRETOR DE VENDAS Mitchell Beaton
GERENTE EXECUTIVO DE MARKETING Chris Ruel
GERENTE DE PRODUTOS SÊNIOR DA MICROSOFT Merrick Van Dongen da Microsoft Learning
ASSISTENTE DO PROGRAMA EDITORIAL Jennifer Lartz
GERENTE DE CONTEÚDO Micheline Frederick
EDITOR DE PRODUÇÃO Amy Weintraub
DIRETOR DE CRIAÇÃO Harry Nolan
DESIGNER DA CAPA Jim O’Shea
TECNOLOGIA E MÍDIA Tom Kulesa/Wendy Ashenberg
Foto da capa: Crédito: © Pgiam/iStockphoto
Este livro foi criado em Garamond pela Aptara, Inc. e impresso e veiculado pela Bind Rite Robbinsville.
A capa foi impressa pela Bind Rite Robbinsville.
Copyright © 2012 da John Wiley & Sons, Inc. Todos os direitos reservados.
Nenhuma parte desta publicação pode ser reproduzida, armazenada em sistema de recuperação ou transmitida sob
qualquer forma ou por qualquer meio eletrônico ou mecânico, fotocópia, gravação, digitalização ou outros (exceto
conforme permitido nas seções 107 ou 108 da lei de direitos autorais dos Estados Unidos publicada em 1976)
sem permissão prévia por escrito da Editora ou autorização mediante pagamento da taxa adequada por cópia para
a Copyright Clearance Center, Inc. – 222 Rosewood Drive, Danvers, MA 01923, site: www.copyright.com. As
solicitações de permissão feitas à Editora devem ser dirigidas ao Departamento de Permissões da John Wiley & Sons,
Inc. – 111 Rio Street, Hoboken, NJ 07030-5774, (201) 748-6011, fax: (201) 748-6008, site: http://www.wiley.com/go/
permissions.
Microsoft, ActiveX, Excel, InfoPath, Microsoft Press, MSDN, OneNote, Outlook, PivotChart, PivotTable, PowerPoint,
SharePoint, SQL Server, Visio, Visual Basic, Visual C#, Visual Studio, Windows, Windows 7, Windows Mobile,
Windows Server e Windows Vista são marcas registradas ou marcas comerciais da Microsoft Corporation nos Estados
Unidos e/ou em outros países. Outros nomes de produtos e empresas mencionados neste documento podem ser marcas
registradas de seus respectivos proprietários.
Os exemplos aqui mencionados de empresas, organizações, produtos, nomes de domínio, endereços de email,
logotipos, indivíduos, locais e eventos são fictícios. Nenhuma associação a empresa, organização, produto, nome de
domínio, endereço de email, logotipo, indivíduo, local ou evento real é intencional, nem deve ser inferida.
Este livro expressa as visões e opiniões do autor. As informações contidas neste livro são fornecidas sem nenhuma
garantia expressa, estatutária ou implícita. Os autores, a John Wiley & Sons, Inc., a Microsoft Corporation e todos
os revendedores e distribuidores envolvidos não serão responsabilizados por nenhum dano causado ou supostamente
causado direta ou indiretamente por este livro.
Fundada em 1807, a John Wiley & Sons, Inc. apresenta-se como uma valiosa fonte de conhecimento e compreensão
há mais de 200 anos, ajudando pessoas ao redor do mundo a atenderem às suas necessidades e atingirem suas metas.
Nossa empresa é baseada em princípios que incluem responsabilidade para com as comunidades que servimos e onde
vivemos e trabalhamos. Em 2008, lançamos uma Iniciativa de Cidadania Corporativa, um esforço global para atender
a desafios ambientais, sociais, econômicos e éticos que enfrentamos em nossos negócios. Entre as questões com as
quais estamos lidando, estão a redução do impacto de carbono das nossas operações, o estabelecimento de padrões de
especificação e suprimento de papel, a aplicação de uma conduta ética em nossos negócios e entre nossos fornecedores
e o suporte à comunidade e organizações de caridade. Para obter mais informações, visite nosso site: www.wiley.com/
go/citizenship.
ISBN 978-0-470-88911-4
Impresso nos Estados Unidos da América
10 9 8 7 6 5 4 3 2 1
d. Você poderá usar o título do MOAC e-Book e Conteúdo do Instrutor aplicável somente durante
a aula que está ensinando o título do MOAC e-Book específico ou pelo período de 180 (cento
e oitenta dias) dias, o que for maior. Depois deste período, você deverá excluir com segurança
todas as cópias do título do MOAC e-Book e Conteúdo do Instrutor em sua posse ou sob seu
controle.
f. Você reconhece que todos os direitos (incluindo, sem limitação, direitos autorais, patentes
e segredos comerciais) relacionados aos MOAC e-Books e ao Conteúdo do Instrutor são de
propridade única e exclusiva da Wiley e de seus licenciadores. A aceitação deste contrato
não torna você o proprietário dos MOAC e-Books e do Conteúdo do Instrutor, mas você terá
uma licença limitada para usar o MOAC e-Book e Conteúdo do Instrutor de acordo com
as disposições deste contrato. Você concorda em proteger o MOAC e-Book e Conteúdo do
Instrutor do uso, carregamento, download, reprodução ou distribuição não autorizado. Você
concorda ainda em não traduzir, descompilar, desmontar ou, de outra forma, fazer engenharia
reversa de qualquer MOAC e-Book ou Conteúdo do Instrutor. A Wiley reserva para si todos os
outros direitos que não foram expressamente concedidos a você neste contrato.
Prefácio da editora
A visão editorial da Wiley para a série Microsoft Official Academic Course é fornecer aos
alunos e instrutores as habilidades e o conhecimento necessários para eles utilizarem a
tecnologia da Microsoft de maneira eficiente em todos os aspectos de suas vidas pessoais
e profissionais. É preciso fornecer uma instrução de qualidade para ajudar tanto os
educadores quanto os alunos a obterem o máximo das ferramentas de software da Microsoft
e se tornarem mais produtivos. Assim sendo, nossa missão é tornar nossos programas
instrucionais companheiros educacionais confiáveis para a vida toda.
Para cumprir essa missão, a Wiley e a Microsoft estabeleceram uma parceria para
desenvolver programas educacionais da mais alta qualidade para profissionais da informação,
profissionais de TI e desenvolvedores. O material criado por essa parceria leva a marca
“Microsoft Official Academic Course”, garantindo a instrutores e alunos que o conteúdo
desses livros didáticos tenha total aprovação da Microsoft e os livros forneçam informações
e instruções de extrema qualidade sobre os produtos da Microsoft. Os livros didáticos do
Microsoft Official Academic Course são “oficiais” em mais de um sentido, eles compõem
o curso sancionado oficialmente para os membros do programa Microsoft IT Academy.
A série Microsoft Official Academic Course concentra-se no desenvolvimento da força de
trabalho. Esses programas destinam-se a alunos que desejam entrar na força de trabalho,
mudar de emprego ou embarcar em novas carreiras como profissionais da informação,
profissionais de TI e desenvolvedores. Os programas Microsoft Official Academic Course
atendem às necessidades dos alunos enfatizando cenários autênticos de local de trabalho
com vários projetos, exercícios, casos e avaliações.
Os Microsoft Official Academic Courses estão ligados a uma ampla pesquisa e análise de
tarefas de trabalho da Microsoft, a mesma pesquisa e análise utilizada para criar os exames
MCITP (Microsoft Certified Information Technology Professional). Os livros didáticos têm
como foco habilidades reais para trabalhos reais. Como os alunos trabalham por meio de
projetos e exercícios nos livros, eles aprimoram seu nível de conhecimento e sua capacidade
de aplicar a tecnologia mais recente da Microsoft às tarefas do dia a dia. Esses alunos
também recebem credenciais que agregam valor ao currículo e podem ajudá-los a encontrar
um emprego, manter o emprego atual ou dar continuidade à sua formação.
Atualmente, o conceito de aprendizado contínuo é uma necessidade primordial. As funções
de trabalho, e até categorias inteiras de trabalho, estão mudando tão rápido que nenhum de
nós consegue se manter competitivo e produtivo sem atualizar continuamente as habilidades
e capacidades. As ofertas do Microsoft Official Academic Course, e seu foco na preparação
para o exame de certificação da Microsoft, fornecem um meio para as pessoas adquirirem
e atualizarem suas habilidades e seu conhecimento de forma eficiente. A Wiley ajuda os
alunos nessa investida por meio do desenvolvimento e da distribuição dos cursos como a
editora acadêmica oficial da Microsoft.
Hoje, a editoração educacional exige atenção para fornecer não só uma impressão de
qualidade, mas também conteúdo eletrônico robusto. Com a integração dos produtos do
Microsoft Official Academic Course, da WileyPLUS e das certificações da Microsoft,
estamos mais bem preparados para fornecer a alunos e professores soluções eficientes de
aprendizado.
Bonnie Lieberman
Gerente geral e vice-presidente sênior
■ Recursos pedagógicos
O livro didático do MOAC para Conceitos básicos de desenvolvimento de software foi
elaborado para cobrir todos os objetivos de aprendizado do exame MTA 98-361, que é
chamado de “objetivo do exame”. Os objetivos do exame MTA (Microsoft Technology
Associate) são destacados ao longo do livro didático. Muitos recursos pedagógicos foram
desenvolvidos especificamente para o programa Microsoft Official Academic Course.
A apresentação de informações processuais e conceitos técnicos detalhados distribuídos
ao longo do livro aumenta os desafios, tanto para o aluno quanto para o instrutor. O tour
ilustrado pelo livro, mostrado a seguir, fornece um guia para os recursos avançados que
contribuem para o plano pedagógico do programa Microsoft Official Academic Course.
A seguir, temos uma lista dos principais recursos em cada lição projetada para preparar
os alunos para o sucesso enquanto dão continuidade à sua formação de TI, nos exames de
certificação e no local de trabalho.
• Cada lição começa com uma Matriz de habilidades da lição. Mais do que uma lista
padrão dos objetivos de aprendizado, a Matriz de habilidades da lição correlaciona
cada habilidade de software abordada na lição com o objetivo específico do exame.
• Exercícios passo a passo concisos e frequentes ensinam os alunos a utilizar novos
recursos e lhes oferecem a oportunidade de praticar o que foi aprendido. Etapas
numeradas fornecem instruções passo a passo detalhadas para ajudar os alunos a
desenvolver habilidades de software.
• Ilustrações– mais especificamente, imagens de tela, fornecem feedback visual
enquanto os alunos trabalham nos exercícios. As imagens reforçam conceitos
importantes, fornecem dicas visuais sobre as etapas e permitem que os alunos
verifiquem o seu progresso.
• Listas dos Principais termos são exibidas no começo de cada lição apresentando aos
alunos um vocabulário técnico importante. Esses termos são exibidos em negrito e
itálico na parte da lição em que são definidos.
• Auxílios ao leitor pontuais e envolventes, localizados em todas as lições, informam
aos alunos por que o tópico é relevante (O resultado) e fornecem dicas úteis (Tome
nota). Os Auxílios ao leitor também oferecem informações adicionais relevantes ou de
plano de fundo que agregam valor à lição.
• Os recursos Pronto para certificação ao longo do texto indicam aos alunos onde
um objetivo específico de certificação é abordado. Eles permitem que os alunos
verifiquem se entenderam um objetivo específico de MTA e, se necessário, revisem a
seção da lição na qual esse objetivo foi abordado. O MOAC oferece preparação total
para a certificação MTA.
• Perguntas no final das lições: a seção Avaliação de conhecimento fornece várias
perguntas de múltipla escolha, verdadeiro ou falso, correspondência e preenchimento
de lacunas.
• Exercícios no final das lições: os cenários de caso das seções Avaliação de competência
e Avaliação de proficiência e os exercícios de Local de trabalho pronto são projetos que
testam a capacidade de os alunos aplicarem o que aprenderam na lição.
www.wiley.com/college/microsoft ou ligue para o número de chamada gratuita: 1+(888) 764-7001 (somente Canadá e
Estados Unidos) | vii
viii | Tour ilustrado pelo livro
■ Recursos da lição
2 LIÇÃO
Introdução à
programação
orientada a objeto
M AT R I Z D E H A B I L I D A D E S D A L I Ç Ã O
Matriz de habilidades da lição
Habilidades/Conceitos Objetivo do exame MTA Número do objetivo do
exame MTA
Noções básicas sobre objetos Compreender os conceitos 2,1
básicos de classes.
Noções básicas sobre Compreender o armazenamento do 1,1
valores e referências computador e os tipos de dados.
Noções básicas sobre Compreender o encapsulamento. 2,4
encapsulamento
Noções básicas sobre herança Compreender a herança. 2,2
Noções básicas sobre polimorfismo Compreender o polimorfismo. 2,3
Noções básicas sobre interfaces Compreender o encapsulamento. 2,4
P R I N C I PA I S T E R M O S
modificador de acesso encapsulamento polimorfismo
acessadores eventos propriedades
classes abstratas
propriedades autoimplementadas
herança
interfaces
tipo de referência
classes seladas
Principais Introdução à programação | 3
classe
construtores
método
namespace
assinatura
números de estáticos
termos Por exemplo, a figura 1-1 mostra um fluxograma que insere dois números, compara-os
e gera a saída do maior número.
delegados objetos tipo de valor
32
Diagramas
Auxílio ao leitor de informativos
referência cruzada
Introdução à programação | 9
Como você pode ver, esse fluxograma lista todas as etapas necessárias na ordem correta
REFERÊNCIA C# fornece vários tipos de dados internos que você pode usar nos seus programas. Você para executar a operação. O fluxo de controle começa com o símbolo Iniciar e termina
CRUZADA
também pode definir novos tipos, especificando uma estrutura de dados, como uma classe
ou um struct. Este capítulo se concentra em alguns tipos de dados internos mais usados com o símbolo Parar. O processo e os símbolos das operações de entrada/saída sempre
Você poderá encontrar
mais informações com frequência. têm uma única entrada e uma única saída. Por outro lado, o símbolo de decisão tem uma
sobre como criar seus A tabela 1-3 lista vários tipos de dados internos usados com frequência e disponíveis única entrada, mas várias saídas. Você pode testar um fluxograma, executando um teste
próprios tipos de dados em C#. Os tamanhos listados na tabela referem-se a um computador que executa completo. Nesse tipo de teste, você rastreia manualmente as etapas do fluxograma com
na lição 2. um sistema operacional de 32 bits, como o Windows 7 de 32 bits. Para um sistema os dados de teste para verificar se os caminhos corretos estão sendo seguidos.
operacional de 64 bits, como o Windows 7 de 64 bits, esses tamanhos serão diferentes.
Uma matriz é uma coleção de itens em que cada item pode ser acessado por um
índice exclusivo.
Uma matriz em C# é normalmente usada para representar uma coleção de itens de tipo
semelhante. Uma declaração de matriz de exemplo é mostrada no código a seguir:
int[] numbers = { 1, 2, 3, 4, 5 };
Essa declaração cria uma matriz identificada pelos números de nome. Essa matriz é capaz
de armazenar uma coleção de cinco números inteiros. Essa declaração também inicializa
cada um dos itens de matriz respectivamente pelos números 1 a 5.
Qualquer item de matriz pode ser diretamente acessado usando um índice. No .NET
Framework, os índices de matriz são de base zero. Isso significa que, para acessar
o primeiro elemento de uma matriz, você usa o índice 1; para acessar o segundo
elemento, você usa o índice 2 e assim por diante.
Para acessar um elemento de matriz individual, você usa o nome da matriz seguido
do índice entre colchetes. Por exemplo, numbers[0] retornará o valor 1 da matriz
declarado acima, e numbers[4] retornará o valor 5. É inválido acessar uma matriz fora
www.wiley.com/college/microsoft ou ligue para o número de chamada gratuita: 1+(888) 764-7001 (somente Canadá e Estados Unidos)
Tour ilustrado pelo livro | ix
44 | lição 2
O RESULTADO
Um tipo de valor armazena diretamente um valor, ao passo que um tipo de referência
armazena apenas uma referência a um valor real. Auxílio ao leitor “O resultado”
Um tipo de valor armazena dados diretamente na própria memória. Por outro lado,
os tipos de referência armazenam apenas uma referência a um local de memória;
aqui, os dados reais são armazenados no local de memória que está sendo referenciado.
A maioria dos tipos de dados elementares internos (como bool, int, char, double etc.) 4 | Lição 1
são tipos de valor. Os tipos de dados definidos pelo usuário criados com a palavra-chave
struct também são tipos de valor. Os tipos de referência incluem os tipos criados com
as palavras-chave object, string, interface, delegate e class. Tabela 1-2
Uma tabela de decisões para Quantidade < 10 S N N N
Noções básicas sobre structs calcular descontos
Quantidade < 50 S S N N
A palavra-chave struct é usada para criar tipos definidos pelo usuário que consistem Quantidade < 100 S S S N
em pequenos grupos de campos relacionados. Os structs são tipos de valor — ao
contrário das classes, que são tipos de referência. Desconto 5% 10% 15% 20%
fáceis de ler
1 20, 30, 10, 40 20, 30, 10, 40 O algoritmo compara os dois primeiros adicionar outras linguagens ao sistema. Embora a sintaxe e o vocabulário de cada linguagem possam
elementos (20 e 30); como eles estão ser diferentes, cada uma ainda poderá usar as bibliotecas de classe base fornecidas pelo Framework.
na ordem correta, nenhuma permuta
é necessária.
2 20, 30, 10, 40 20, 10, 30, 40 O algoritmo compara os dois
elementos seguintes (30 e 10);
como eles estão fora de ordem, Auxílio ao leitor
os elementos são trocados.
3 20, 10, 30, 40 20, 10, 30, 40 O algoritmo compara os dois “Mais informações”
elementos seguintes (30 e 40); como
eles estão na ordem correta, nenhuma
permuta é necessária.
Conforme mostra a tabela 3-1, no final da primeira passagem, BubbleSort realizou uma
permuta, e é possível que os itens ainda não estejam totalmente classificados. Portanto,
BubbleSort dá uma outra passagem na lista, conforme ilustrado na tabela 3-2.
Tabela 3-2
Segunda passagem de Etapa Antes Depois Comentários
BubbleSort
1 20, 10, 30, 40 10, 20, 30, 40 O algoritmo compara os dois primeiros
elementos (20 e 10); como eles estão
fora de ordem, os elementos são
trocados.
2 10, 20, 30, 40 10, 20, 30, 40 O algoritmo compara os dois
elementos seguintes (20 e 30); como
eles estão na ordem correta, nenhuma
permuta é necessária.
3 10, 20, 30, 40 10, 20, 30, 40 O algoritmo compara os dois
elementos seguintes (30 e 40); como
eles estão na ordem correta, nenhuma
permuta é necessária.
68 | lição 3
O teste de software é usado para assegurar a qualidade do produto final. O teste pode
identificar possíveis lacunas entre as expectativas em relação ao sistema descritas no
documento de requisitos e o comportamento real do sistema.
Entre os participantes mais críticos na atividade de teste de software estão os testadores
que verificam o aplicativo em execução para se certificar de que ele atende aos requisitos
identificados. Quando esses testadores identificam qualquer falha no aplicativo, eles
atribuem cada falha a uma pessoa apropriada que possa consertá-la. Por exemplo, uma
falha de código seria atribuída de volta a um desenvolvedor para que ele (ou ela) possa
remediar o erro.
Imagens
outra variável do }
mesmo tipo, apenas
as referências são 3. Selecione Depurar > Iniciar sem Depuração. Uma janela de console será exibida
mostrando os valores de p1.X e rect1.Length.
de tela copiadas. Como
resultado, após
a cópia, as duas
4. SALVE seu projeto.
PAUSE. Deixe o projeto aberto para ser usado no próximo exercício.
variáveis apontarão
para o mesmo objeto. Aqui, a primeira parte do programa cria uma cópia do tipo de valor Point, e a segunda
metade cria uma cópia do tipo de referência Rectangle.
Vamos começar analisando como a cópia de um tipo de valor é feita. Para começar,
quando a instrução a seguir for executada, uma nova variável p2 será criada na memória,
e seu conteúdo será copiado a partir da variável p1:
Point p2 = p1;
Após a execução dessa instrução, a variável p2 será criada, e o conteúdo da variável p1
será copiado para a variável p2. Tanto p1 quanto p2 têm seu próprio conjunto de valores
disponíveis em seus respectivos locais de memória. Portanto, quando a instrução a seguir
for executada:
p2.X = 100;
Um programa C# é composto por uma ou mais classes. Uma classe é um conjunto
de dados e métodos. Por exemplo, o código da figura 1-3 define uma única classe Ela só afetará o valor de X correspondente ao local de memória da variável p2. O valor de
REFERÊNCIA denominada Program nas linhas de 5 a 11. Uma classe é definida usando a palavra-chave X para a variável p1 permanece inalterado.
CRUZADA class, seguida pelo nome de classe. O conteúdo de uma classe é definido entre uma chave
de abertura ({) e uma chave de fechamento (}).
Você poderá encontrar
mais informações sobre A linha 3 do código na figura 1-3 define um namespace, Lesson01. Os namespaces são
classes na lição 2. usados para organizar classes e identificá-las com exclusividade. O namespace e os nomes
de classe são combinados para criar um nome de classe totalmente qualificado. Por
exemplo, o nome de classe totalmente qualificado da classe Program é Lesson01.Program.
C# requer que o nome totalmente qualificado de uma classe seja exclusivo. Como
resultado, você não poderá ter outra classe com nome Program no namespace Lesson01,
mas poderá ter uma classe com nome Program em outro namespace, por exemplo,
Lesson02. Aqui, a classe Program definida no namespace Lesson02 é identificada
exclusivamente pelo seu nome de classe totalmente qualificado, Lesson02.Program.
REFERÊNCIA O .NET Framework fornece inúmeras classes úteis, organizadas em vários namespaces.
CRUZADA
O namespace System contém algumas das classes base usadas com mais frequência.
Você poderá encontrar Uma classe desse tipo no namespace System é Console. A classe Console fornece
mais informações sobre funcionalidade de entrada e saída do aplicativo de console. A linha 9 do código na figura
métodos na lição 2. 1-3 refere-se à classe Console e chama seu método WriteLine. Para acessar o método
WriteLine de forma inequívoca, você deve escrevê-lo desta forma:
System.Console.WriteLine(“olá, mundo”);
TOME NOTA
* Como os nomes de classe aparecem com frequência no código, escrever sempre o nome
de classe totalmente qualificado será entediante e tornará o programa muito detalhado.
Cada instrução C#
Você pode solucionar esse problema usando a diretiva C# using (consulte o código
deve terminar com na linha 1 da figura 1-3). A diretiva using permite que você use as classes em um
ponto-e-vírgula (;). namespace sem precisar qualificar totalmente o nome de classe.
A classe Program define um único método pelo nome Main (consulte as linhas 7 a 10
da listagem de código na figura 1-3). Main é um método especial, pois também serve
como um ponto de entrada para o programa. Quando o tempo de execução executa um
www.wiley.com/college/microsoft ou ligue para o número de chamada gratuita: 1+(888) 764-7001 (somente Canadá e Estados Unidos)
Tour ilustrado pelo livro | xi
Os níveis de teste são definidos pela parte em que os testes ocorrem no ciclo de vida RESUMO DE HABILIDADES
de desenvolvimento do software. Há cinco níveis distintos de teste:
• Teste de unidade: o teste de unidade verifica a funcionalidade de uma unidade de Nesta lição, você aprendeu que:
código. Por exemplo, uma unidade de teste pode avaliar se um método retorna o valor
• Um banco de dados relacional organiza as informações em tabelas. Uma tabela
correto. O teste de unidade é um teste caixa branca e é realizado com frequência pelo
é uma lista de linhas e colunas.
desenvolvedor que está escrevendo o código. O teste de unidade muitas vezes usa
• Um design de banco de dados relacional é o processo que determina a estrutura de
uma ferramenta automatizada que pode simplificar o desenvolvimento dos casos e banco de dados relacional adequada para atender aos requisitos comerciais.
também acompanhar se uma modificação do código causa a falha de qualquer um • Os diagramas de relacionamento entre entidades são usados para modelar as
dos testes de unidade existentes. O Visual Studio tem suporte interno para o teste de entidades, seus atributos e os relacionamentos entre as entidades. Esses diagramas
unidade. Você também pode usar ferramentas de software livre, como o NUnit, para de relacionamento entre entidades podem ajudá-lo a determinar quais dados
automatizar os testes de unidade para o código do .NET Framework. precisam ser armazenados em um banco de dados.
• Teste de integração: o teste de integração avalia a interface entre os componentes • O processo de normalização de dados garante que um design de banco de dados não
tenha problemas que possam levar à perda da integridade dos dados. A maioria dos
de software. O teste de integração pode ser executado de forma incremental enquanto problemas de design podem ser resolvidos, garantindo que as tabelas atendam aos
requisitos da terceira forma normal.
• A linguagem SQL linguagem fornece instruções, como SELECT, INSERT, UPDATE
e DELETE, para trabalharem com dados relacionais.
• Um procedimento armazenado é um conjunto de instruções SQL que são
armazenadas em um banco de dados. Os procedimentos armazenados podem ser
usados por vários aplicativos.
• As classes XmlReader e XmlWriter fornecem uma maneira rápida, sem
armazenamento em cache e somente de encaminhamento para ler ou gravar dados
XML. A classe XmlDocument é uma representação na memória de dados XML
e permite a navegação e a edição do documento XML.
• A classe DataSet é uma representação na memória de dados relacionais.
A classe DataAdapter funciona como ponte entre a fonte de dados e o DataSet.
O DataAdapter armazena a conexão de dados e os comandos de dados necessários
para se conectar à fonte de dados.
■ Avaliação de proficiência
Cenário 2-1: substituindo o método ToString
Suponha que você esteja escrevendo um código para uma classe Product. A classe Product
contém o nome e o preço de um produto. Você precisa substituir o método ToString
da classe base (System.Object) para fornecer informações sobre os objetos da classe
de produto para o código de chamada. Qual código você precisa escrever para a classe
Product a fim de atender a esse requisito?
www.wiley.com/college/microsoft ou ligue para o número de chamada gratuita: 1+(888) 764-7001 (somente Canadá e Estados Unidos)
Convenções e recursos
utilizados neste livro
Este livro utiliza fontes, símbolos e convenções de título específicos para destacar
informações importantes ou para chamar a atenção para etapas especiais. Para obter mais
informações sobre os recursos de cada lição, consulte a seção Tour ilustrado pelo livro.
Convenção Significado
Este recurso fornece um breve resumo do material coberto
na seção seguinte.
O RESULTADO
Os programas Microsoft Official Academic Course são acompanhados por uma rica
variedade de recursos que incorporam elementos visuais detalhados para formar um
pacote coeso do ponto de vista pedagógico. Esses recursos fornecem todo o material de
que os instrutores precisam para implantar e ministrar seus cursos. Os recursos disponíveis
online para download incluem:
• O MSDN Academic Alliance (MSDN AA) foi projetado para fornecer as
ferramentas de desenvolvedor, as tecnologias e os produtos mais econômicos
e fáceis de usar para professores e alunos nos laboratórios, nas salas de aula e nos
computadores dos alunos. Uma assinatura gratuita por três anos está disponível aos
membros qualificados do MOAC.
Observação: o Microsoft Windows 2008 Server, o Microsoft Windows 7 e o
Microsoft Visual Studio podem ser baixados do MSDN AA para serem utilizados
pelos alunos neste curso.
• O Guia do Instrutor contém soluções para todos os exercícios do livro didático
e programas para vários períodos. Ele também inclui resumos de capítulo e
observações de aula. O Guia do Instrutor está disponível no site de conteúdo extra do
livro didático (http://www.wiley.com/college/microsoft).
• O Banco de teste contém centenas de perguntas de múltipla escolha, verdadeiro
ou falso, resposta curta e dissertação e está disponível para download no site de
conteúdo extra do livro didático do instrutor (www.wiley.com/college/microsoft).
Um gabarito completo também é fornecido.
• Um conjunto completo de apresentações e imagens do PowerPoint está disponível
no site de conteúdo extra do livro didático do instrutor (http://www.wiley.com/
college/microsoft) para aprimorar as apresentações em sala de aula. São fornecidos,
aproximadamente, 50 slides do PowerPoint para cada lição. Feitas sob medida para
a matriz de habilidades e os tópicos do texto, essas apresentações são criadas para
apresentar conceitos importantes que são abordados ao longo do texto. Todas as
imagens do texto estão no site de conteúdo extra do livro didático do Instrutor
(http://www.wiley.com/college/microsoft). Você pode incorporá-las nas suas
apresentações do PowerPoint ou criar suas próprias transparências e folhetos. A
utilização desses elementos visuais nas discussões de sala de aula, pode ajudar você
a chamar a atenção dos alunos para elementos-chave das tecnologias abordadas e
ajudá-los a compreender como utilizá-las de maneira eficiente no local de trabalho.
• Para aprimorar a experiência de sala de aula, nada melhor do que ouvir os colegas
para obter ideias e inspiração. A Wiley Faculty Network conecta os professores
à tecnologia, facilita a troca de melhores práticas e ajuda a aprimorar a eficiência
e a efetividade das instruções. As atividades da Faculty Network incluem treinamento
e tutoriais de tecnologia, seminários virtuais, trocas de experiências e ideias entre
colegas, consultoria pessoal e compartilhamento de recursos. Para obter detalhes,
visite o site www.WhereFacultyConnect.com.
■ Recursos adicionais
Site de conteúdo extra do livro didático (www.wiley.com/college/microsoft)
O site de conteúdo extra do livro didático do aluno para a série MOAC inclui os recursos,
os arquivos de exercício e os links da Web que serão utilizados com este curso.
As Wiley Desktop Editions da série MOAC são versões eletrônicas inovadoras dos livros
didáticos impressos. Os alunos adquirem a versão para desktop por até metade do preço do
texto impresso nos Estados Unidos e ganham as vantagens de permanência e portabilidade.
As Wiley Desktop Editions oferecem aos alunos vários benefícios adicionais que não estão
disponíveis com outras soluções de texto eletrônico.
Elas NÃO são assinaturas; os alunos baixam a Wiley Desktop Edition para a área de
trabalho dos seus computadores. Os alunos poderão manter o conteúdo adquirido pelo
tempo que desejarem. Depois que a Wiley Desktop Edition é baixada para a área de trabalho
do computador, os alunos passam a ter acesso imediato a todo o conteúdo sem precisar
estar online. Os alunos também podem imprimir as seções que preferem ler impressas.
Além disso, eles têm acesso a recursos totalmente integrados na sua Wiley Desktop Edition.
Desde realçar partes do texto até fazer anotações e compartilhá-las com colegas, os alunos
podem personalizar facilmente a Wiley Desktop Edition enquanto leem ou acompanham a
aula.
A MTA apresenta um novo padrão para medir e validar o conhecimento básico de tecnologia
dos alunos dentro da própria sala de aula mantendo intactos seu orçamento e seus recursos
de ensino. A MTA ajuda as instituições a destacarem-se como provedoras inovadoras de
credenciais requisitadíssimas no setor e é facilmente implantada com um pacote simples,
conveniente e acessível de exames de certificação de tecnologia para iniciantes. Ela também
permite que os alunos explorem caminhos de carreira na área de tecnologia sem precisar
investir muito em tempo e recursos, ao mesmo tempo que fornece uma base de carreira e
a confiança necessária para obter sucesso nos estudos avançados e nas futuras empreitadas
vocacionais.
Além de fornecer aos alunos uma certificação de nível de entrada da Microsoft, a MTA
foi projetada para ser encarada como um primeiro passo em direção às certificações
de tecnologia mais avançadas da Microsoft, como a certificação Microsoft Certified
Technology Specialist (MCTS).
Implementar um novo programa de certificação na sua sala de aula nunca foi tão fácil
quanto agora com a MTA Campus License. Com a aquisição única de uma MTA Campus
License de 12 meses e 1.000 exames, você não precisa mais solicitar orçamentos ad hoc
nem comprar vouchers de exame regularmente. Agora você poderá planejar seu orçamento
incluindo apenas um pequeno custo para o ano todo e aplicar os exames MTA a seus alunos
e outros professores em todo o campus, onde e quando quiser.
A MTA Campus License fornece um pacote conveniente e acessível de certificações de
tecnologia de nível de entrada projetadas para capacitar os educadores e motivar os alunos
enquanto desenvolvem a base para suas carreiras.
A MTA Campus License é administrada pela Certiport (provedora de exames MTA
exclusiva da Microsoft).
Para saber mais sobre como receber um certificado de Microsoft Technology Associate
e consultar a disponibilidade do exame, visite o site www.microsoft.com/learning/mta.
Gostaríamos de agradecer aos diversos revisores Sharon Moran, Hillsborough Community College
que analisaram cuidadosamente o documento e Keith Hoell, Briarcliffe College e Queens College –
forneceram feedbacks inestimáveis para possibilitar o CUNY
desenvolvimento de um material instrucional da mais alta Mark Hufnagel, Lee County School District
qualidade:
Rachelle Hall, Glendale Community College
Yuke Wang, Universidade do Texas em Dallas Scott Elliott, Christie Digital Systems, Inc.
Palaniappan Vairavan, Bellevue College Gralan Gilliam, Kaplan
Harold “Buz” Lamson, ITT Technical Institute Steve Strom, Butler Community College
Colin Archibald, Valencia Community College John Crowley, Bucks County Community College
Catherine Bradfield, DeVry University Online Margaret Leary, Northern Virginia Community College
Robert Nelson, Blinn College Sue Miner, Lehigh Carbon Community College
Kalpana Viswanathan, Bellevue College Gary Rollinson, Cabrillo College
Bob Becker, Vatterott College Al Kelly, University of Advancing Technology
Carol Torkko, Bellevue College Katherine James, Seneca College
Bharat Kandel, Missouri Tech
Linda Cohen, Forsyth Technical Community College
Candice Lambert, Metro Technology Centers
Susan Mahon, Collin College
Mark Aruda, Hillsborough Community College
Claude Russo, Brevard Community College
David Koppy, Baker College
1 Introdução à programação 1
Apêndice A 177
Índice 179
Lição 4: Noções básicas sobre Noções básicas sobre aplicativos MDI (interface de
vários documentos) 126
aplicativos Web 85
Noções básicas sobre aplicativos de console 129
Trabalhando com parâmetros de linha de comando 130
Matriz de domínio objetiva 85
Noções básicas sobre os serviços Windows 131
Principais termos 85 Criando um serviço Windows 132
Noções básicas sobre o desenvolvimento de páginas Resumo de habilidades 137
da Web 85
Noções básicas sobre HTML 86 Avaliação de conhecimento 138
Noções básicas sobre folhas de estilos em cascata 88 Avaliação da competência 140
Noções básicas sobre JavaScript 92 Avaliação de proficiência 141
Noções básicas sobre programação do lado do cliente
versus lado do servidor 94
Noções básicas sobre o desenvolvimento de Lição 6: Noções básicas sobre bancos
aplicativos ASP.NET 95 de dados 142
Noções básicas sobre o ciclo de vida da página do ASP.
NET e o modelo de eventos 96
Matriz de domínio objetiva 142
Noções básicas sobre gerenciamento de estado 99
Principais termos 142
Noções básicas sobre a hospedagem Web do
IIS 104 Noções básicas sobre conceitos de banco de dados
Noções básicas sobre os Serviços de Informações da relacional 142
Internet 105 Noções básicas sobre bancos de dados 143
Criando diretórios virtuais e sites 105 Noções básicas sobre conceitos de banco de dados
Implantando aplicativos Web 106 relacional 143
Noções básicas sobre design de banco de dados
Noções básicas sobre o desenvolvimento de serviços relacional 144
Web 107 Noções básicas sobre diagramas de relacionamento
Introdução ao SOAP 107
entre entidades 144
Introdução ao WSDL 108
Noções básicas sobre normalização de dados 146
Criando serviços Web 108
Consumindo serviços Web 112 Noções básicas sobre os métodos de consulta de
banco de dados 149
Resumo de habilidades 115 Trabalhando com consultas SQL 150
Avaliação de conhecimento 115 Trabalhando com procedimentos armazenados 159
Avaliação da competência 118 Noções básicas sobre métodos de conexão de banco
Avaliação de proficiência 119 de dados 164
Trabalhando com arquivos simples 164
Trabalhando com XML 167
Lição 5: Noções básicas sobre Trabalhando com DataSet 170
aplicativos da área de Resumo de habilidades 173
trabalho 120 Avaliação de conhecimento 173
Avaliação da competência 176
Matriz de domínio objetiva 120 Avaliação de proficiência 176
Principais termos 120
Noções básicas sobre os aplicativos do Windows
Forms 120 Apêndice A 177
Como projetar um Windows Form 121 Índice 179
Noções básicas sobre o modelo de evento do Windows
Form 123
Usando a herança visual 123
P R I N C I PA I S
TERMOS estruturas de decisão instrução if
algoritmo tabela de decisões instrução if-else
matriz instrução padrão métodos
código binário Loop do-while operador
sistema de número binário
exceção Recursão
maiúsculas e minúsculas
bloco finally bloco switch
classe
fluxograma Instrução switch
programas de computador
(programas) Loop for bloco try-catch-finally
constante Loop foreach variável
tipos de dados linguagem de alto nível Loop while
1
2 | Lição 1
Introdução a algoritmos
Um algoritmo é conjunto finito e ordenado de etapas para solucionar um problema
específico.
Tabela 1-1
Símbolos comuns
de fluxograma
Introdução à programação | 3
Por exemplo, a figura 1-1 mostra um fluxograma que insere dois números, compara-os
e gera a saída do maior número.
Figura 1-1
Um fluxograma simples que
compara dois números e gera
a saída do maior dos dois
Como você pode ver, esse fluxograma lista todas as etapas necessárias na ordem correta
para executar a operação. O fluxo de controle começa com o símbolo Iniciar e termina
com o símbolo Parar. O processo e os símbolos das operações de entrada/saída sempre
têm uma única entrada e uma única saída. Por outro lado, o símbolo de decisão tem uma
única entrada, mas várias saídas. Você pode testar um fluxograma, executando um teste
completo. Nesse tipo de teste, você rastreia manualmente as etapas do fluxograma com
os dados de teste para verificar se os caminhos corretos estão sendo seguidos.
Tabela 1-2
Uma tabela de decisões para Quantidade < 10 S N N N
calcular descontos
Quantidade < 50 S S N N
Quantidade < 100 S S S N
Desconto 5% 10% 15% 20%
Para descobrir qual item de ação aplicar, você deve avaliar cada condição para encontrar
a regra de correspondência e, em seguida, escolher a ação especificada na coluna com
a regra de correspondência. Por exemplo, se o valor de “Quantidade” nos dados de teste
for 75, a primeira regra resultará em “Não”, a segunda regra resultará em “Não”,
e a terceira regra resultará em “Sim”. Portanto, você escolherá o item de ação da coluna
(N, N e S), que define o desconto de 15%.
Introdução ao C#
C# é uma linguagem de programação popular de alto nível que lhe permite escrever
programas de computador em um formato que pode ser compreendido pelo usuário.
C# é uma parte do .NET Framework e se beneficia do suporte ao tempo de execução
e das bibliotecas de classe fornecidas pelo .Framework.
ESCREVER UM PROGRAMA C#
Figura 1-2
Saída do programa em uma
janela de comando
Você também pode executar o programa, abrindo uma janela de comando (cmd.exe)
UMA OUTRA
e, em seguida, navegando para a pasta de saída do projeto, que, por padrão,
MANEIRA é a subpasta bin\debug no local do projeto. Inicie o programa digitando o nome
dele na janela de comando e pressionando Enter.
O programa que você acabou de criar tem uma função trivial, mas, no entanto, é útil para
a compreensão da estrutura, da compilação e da execução do programa. Vamos primeiro
falar sobre a parte de compilação e execução. Isso é o que acontece quando você seleciona
a opção Depurar > Iniciar sem Depurar na etapa 5 acima:
1. O Visual Studio invoca o compilador C# para converter o código C# em uma
linguagem de nível inferior, o código CIL (Common Intermediate Language).
Esse código de baixo nível é armazenado em um arquivo executável denominado
(Lesson01.exe). O nome do arquivo de saída pode ser alterado modificando as
propriedades de um projeto.
2. Em seguida, o Visual Studio gera a saída do projeto e solicita que ele seja
executado pelo sistema operacional. Neste momento, você vê a janela de comando
exibindo a saída.
3. Quando o programa termina, o Visual Studio exibe a seguinte mensagem:
“Pressione qualquer tecla para continuar. . .”. Observe que essa mensagem
só é gerada quando você executa o programa usando a opção Iniciar sem Depurar.
Quando você seleciona a opção de menu Depurar > Iniciar sem Depurar, o Visual Studio
exibe automaticamente o prompt “Pressione qualquer tecla para continuar. . .” A janela
de comando, então, fica aberta para que você examine a saída. Se, entretanto, você
*
TOME NOTA selecionar a opção Depurar > Iniciar Depuração, a janela de comando fechará assim que
for concluída a execução do programa. É importante saber que a opção Iniciar Depuração
fornece recursos de depuração, como a capacidade de pausar um programa em execução em
um determinado ponto e rever o valor das diversas variáveis na memória.
Antes que o código CIL (Common Intermediate Language) seja executado, ele deve ser
convertido primeiro para a arquitetura da máquina na qual será executado. O sistema de
*
TOME NOTA
execução de tempo de execução do .NET Framework se encarrega dessa conversão de
forma oculta, usando um processo denominado compilação Just-In-Time.
A figura 1-3 mostra o programa criado no exercício anterior com números de linha.
Durante esta seção, esses números serão usados para se referir a diferentes estruturas
do programa.
Figura 1-3
Listagem de programa com
números de linha
programa, ele sempre começa no método Main. Um programa pode ter várias classes,
e cada classe pode ter vários métodos, mas deve ter apenas um método Main. Um método
pode, por sua vez, chamar outros métodos. Na linha 9, o método Main está chamando
o método WriteLine da classe System.Console para exibir uma cadeia de caracteres na
janela de comando — e é desse modo que a mensagem é exibida.
O método Main deve ser declarado como static. Um método estático pode ser chamado
*
TOME NOTA em uma classe, mesmo quando nenhuma instância da classe é criada. Você aprenderá
mais sobre isso na próxima lição.
As variáveis em C# são espaços reservados usados para armazenar valores. Uma variável
tem um nome e um tipo de dados. O tipo de dados de uma variável determina quais
valores ele pode conter e qual tipo de operações pode ser executado nele. Por exemplo,
a declaração a seguir cria uma variável denominada number do tipo de dados int e atribui
o valor 10 à variável:
int number = 10;
Quando uma variável é declarada, um local suficientemente grande para conter o valor do
seu tipo de dados é criado na memória do computador. Por exemplo, em uma máquina de
32 bits, uma variável de tipo de dados int precisará de dois bytes de memória. O valor de
uma variável pode ser modificado por outra atribuição, como:
number = 20;
O código acima altera o conteúdo do local da memória identificado pelo número de nome.
Um nome de variável deve começar com letra ou sublinhado e pode conter apenas
*
TOME NOTA letras, números ou sublinhados. Um nome de variável não deve exceder 255 caracteres.
Uma variável também deve ser exclusiva dentro do escopo no qual está definida.
As constantes são campos de dados ou variáveis locais cujo valor não pode
ser modificado.
As constantes são declaradas usando a palavra-chave const. Por exemplo, uma constante
pode ser declarada da seguinte maneira:
const int i = 10;
Isso declara uma constante i de tipo de dados int e armazena o valor 10. Depois que
a constante for declarada, seu valor não poderá ser alterado.
REFERÊNCIA C# fornece vários tipos de dados internos que você pode usar nos seus programas. Você
CRUZADA
também pode definir novos tipos, especificando uma estrutura de dados, como uma classe
Você poderá encontrar ou um struct. Este capítulo se concentra em alguns tipos de dados internos mais usados
mais informações com frequência.
sobre como criar seus A tabela 1-3 lista vários tipos de dados internos usados com frequência e disponíveis
próprios tipos de dados em C#. Os tamanhos listados na tabela referem-se a um computador que executa
na lição 2. um sistema operacional de 32 bits, como o Windows 7 de 32 bits. Para um sistema
operacional de 64 bits, como o Windows 7 de 64 bits, esses tamanhos serão diferentes.
Tabela 1-3
Tipos de dados internos Tipo de dados Tamanho Intervalo de valores
usados com frequência em C#
byte 1 byte 0 a 255
char 2 bytes U+0000 a U+ffff (caracteres Unicode)
short 2 bytes −32,768 to 32,767
Int 4 bytes −2,147,483,648 to 2,147,483,647
long 8 bytes −9,223,372,036,854,775,808 to
9,223,372,036,854,775,807
float 4 bytes ±1.5 × 10-45 a ±3.4 × 1038
double 8 bytes ±5.0e−324 a ±1.7e308
TOME NOTA
* bool 2 bytes True ou false
As versões sem sinal
de short, int e long são string - Zero ou mais caracteres Unicode
ushort, uint e ulong,
respectivamente.
Os tipos sem sinal têm Todos os tipos de dados listados na tabela 1-3 são tipos de valor, exceto string, que é um
o mesmo tamanho tipo de referência. As variáveis que são baseadas diretamente nos tipos de valor contêm
que suas versões com o valor. No caso do tipo de referência, a variável contém o endereço do local de memória
sinal, mas armazenam onde estão armazenados os dados reais. Você aprenderá mais sobre as diferenças entre
muito mais intervalos tipos de valor e tipos de referência na lição 2.
de valores somente
positivos.
NOÇÕES BÁSICAS SOBRE MATRIZES
Uma matriz é uma coleção de itens em que cada item pode ser acessado por um
índice exclusivo.
Uma matriz em C# é normalmente usada para representar uma coleção de itens de tipo
semelhante. Uma declaração de matriz de exemplo é mostrada no código a seguir:
int[] numbers = { 1, 2, 3, 4, 5 };
Essa declaração cria uma matriz identificada pelos números de nome. Essa matriz é capaz
de armazenar uma coleção de cinco números inteiros. Essa declaração também inicializa
cada um dos itens de matriz respectivamente pelos números 1 a 5.
Qualquer item de matriz pode ser diretamente acessado usando um índice. No .NET
Framework, os índices de matriz são de base zero. Isso significa que, para acessar
o primeiro elemento de uma matriz, você usa o índice 1; para acessar o segundo
elemento, você usa o índice 2 e assim por diante.
Para acessar um elemento de matriz individual, você usa o nome da matriz seguido
do índice entre colchetes. Por exemplo, numbers[0] retornará o valor 1 da matriz
declarado acima, e numbers[4] retornará o valor 5. É inválido acessar uma matriz fora
10 | Lição 1
REFERÊNCIA de seus limites definidos. Por exemplo, você obterá um erro se tentar acessar o elemento
CRUZADA
de matriz numbers[5].
O tópico de matrizes
é abordado em mais NOÇÕES BÁSICAS SOBRE OPERADORES
detalhes na lição 3,
Noções básicas sobre Os operadores são símbolos que especificam qual operação executar nos operandos
o desenvolvimento de antes de retornar um resultado.
software em geral.
Os exemplos de operadores incluem +, -, *, / etc., e os operandos podem ser variáveis,
constantes, literais etc. Dependendo de quantos operandos estiverem envolvidos, haverá
três tipos de operadores:
• Operadores unários: os operadores unários trabalham com apenas um operando.
Os exemplos incluem ++x, x++ ou isEven, onde x é do tipo de dados Integer e isEven
é do tipo de dados Boolean.
• Operadores binários: os operadores binários usam dois operandos. Por exemplo,
x + y ou x > y.
• Operadores ternários: os operadores ternários usam três operandos. Há apenas
um operador ternário, ?:, em C#.
Muitas vezes, as expressões envolvem mais de um operador. Nesse caso, o compilador
precisa determinar qual operador terá precedência sobre o(s) outro(s). A tabela 1-4 lista os
operadores C# em ordem de precedência. Quanto mais alto um operador estiver localizado
na tabela, maior será sua precedência. Os operadores com maior precedência são avaliados
antes dos operadores com menor precedência. Os operadores que aparecem na mesma linha
têm a mesma precedência.
Tabela 1-4
Precedência do operador Categoria Operadores
em C#
Primário x.y f(x) a[x] x++ x −− novo typeof marcado
desmarcado
Unário + - ! ~ ++x −−x (T)x
Multiplicativo */%
Aditivo +-
Shift << >>
Relacional e o tipo de teste < > <= >= is as
Igualdade == !=
AND lógico &
XOR lógico ^
OR lógico |
AND condicional &&
OR condicional ||
Ternário condicional ?:
Atribuição = *= /= %= += -= <<= >>= &= ^= |=
int x = 10;
x++; //o valor de x agora é 11
++x++; //o valor de x agora é 12
Entretanto, o modo como os operadores de incremento e de decremento unários
funcionam quando usados como parte de uma atribuição pode afetar os resultados.
Em particular, quando os operadores de incremento e de decremento unários são usados
como prefixos, o valor atual do identificador é retornado antes do incremento ou do
decremento. Por outro lado, quando usado como sufixo, o valor do identificador
é retornado depois que o incremento ou decremento é concluído. Para compreender
o que isso significa, considere o exemplo de código a seguir:
int y = x++; // o valor de y é 12
int z = ++x; // o valor de z é 14
Aqui, na primeira instrução, o valor de x é retornado antes do incremento. Como
resultado, depois que a instrução é executada, o valor de y é 12 e o valor de x é 13.
Por outro lado, na segunda instrução, o valor de x é incrementado antes do retorno do
seu valor para a atribuição. Como resultado, depois que a instrução é executada, o valor
de x e z é 14.
Métodos são blocos de código que contêm uma série de instruções. Os métodos
podem receber dados via argumentos e retornar um valor para o solicitante.
Na listagem de código anterior, você aprendeu sobre o método Main. Os métodos contêm
a ação em um programa. Mais precisamente, um método é um conjunto de instruções que
são executadas quando o método é chamado.
PRONTO PARA
O método Main não retorna um valor de volta para o código de chamada. Isso é indicado
CERTIFICAÇÃO
Você compreende usando a palavra-chave void. Se um método tivesse que retornar um valor, o tipo de dados
os elementos principais apropriado para o valor de retorno seria usado em vez de void.
da programação, como
variáveis, tipos de Os membros de classe podem ter modificadores, como static, public e private. Esses
dados, operadores modificadores especificam como e onde os membros de classe podem ser acessados. Você
e métodos? aprenderá mais sobre esses modificadores na lição 2.
1.1
A instrução if
A instrução if somente executará uma sequência de instruções específica
se a expressão booliana correspondente resultar em true.
12 | Lição 1
Algumas vezes nos seus programas, você desejará que uma sequência de instruções
somente seja executada se uma determinada condição for verdadeira. Em C#, isso
é possível usando a instrução if. Execute as etapas a seguir para criar um programa
que use uma instrução if.
USAR A INSTRUÇÃO IF
Figura 1-4
Fluxograma equivalente da
instrução if de exemplo
A instrução if-else
A instrução if-else permite que seu programa execute uma ação se a expressão
booliana resultar em true e uma ação diferente se ela resultar em false.
Execute as etapas a seguir para criar um programa de exemplo que use a instrução if-else.
Figura 1-5
Fluxograma equivalente da
instrução if-else de exemplo
A instrução switch
A instrução switch permite a ramificação multidirecional. Em muitos casos, o uso
da instrução switch pode simplificar uma combinação complexa de instruções if-else.
TOME NOTA
* A instrução switch consiste na palavra-chave switch, seguida de uma expressão entre
A expressão após parênteses e um bloco switch. O bloco switch pode incluir uma ou mais instruções case
a instrução case deve ou uma instrução default. Quando a instrução switch é executada, dependendo do valor
ser uma expressão da expressão switch, o controle é transferido para uma instrução case correspondente.
constante e deve Se a expressão não coincidir com nenhuma das instruções case, o controle será transferido
ser do tipo de dados para a instrução default. A expressão switch deve estar entre parênteses.
correspondente
à expressão switch. Execute as etapas a seguir para criar um programa que use a instrução switch para avaliar
expressões simples.
No entanto, se nenhum código for especificado após a instrução case, não haverá
problema se o controle passar para a instrução case subsequente. O código a seguir
demonstra como isso pode ser útil:
public static void TestSwitchFallThrough()
{
DateTime dt = DateTime.Today;
switch (dt.DayOfWeek)
{
case DayOfWeek.Monday:
case DayOfWeek.Tuesday:
case DayOfWeek.Wednesday:
case DayOfWeek.Thursday:
case DayOfWeek.Friday:
Console.WriteLine(“Hoje é um dia de semana”);
break;
default:
Console.WriteLine(“Hoje é um dia de semana”);
break;
}
PRONTO PARA
CERTIFICAÇÃO }
Você compreende
o significado de Aqui, se o valor da expressão dt.DayofWeek for DayOfWeek.Monday, o primeiro case
estruturas de decisão terá correspondência, mas, como nenhum código (ou uma instrução de transferência
do computador, como de controle) é especificado, a execução passará para a próxima instrução, resultando
ramificação e repetição? na exibição da mensagem “Hoje é um dia de semana” na janela de comando.
1.2
Você pode decidir se deseja usar instruções if-else ou uma instrução switch com base
na natureza da comparação e da legibilidade do código. Por exemplo, o código do
método TestIfElse toma decisões com base nas condições mais adequadas de uso
TOME NOTA
* com as instruções if-else. No método TestSwitch, as decisões são baseadas em valores
constantes, portanto, o código é muito mais legível quando é escrito como uma
instrução switch.
Essas instruções de controle de repetição podem ser usadas para executar as instruções
no corpo do loop várias vezes, dependendo do critério de término do loop.
Um loop também pode ser terminado usando uma das várias instruções de transferência
de controle que transferem o controle fora do loop. Essas instruções são break, goto,
return ou throw. Finalmente, a instrução continue pode ser usada para passar o controle
para a próxima iteração do loop sem sair do loop.
Noções básicas sobre o loop while
O loop while executa um bloco de instruções repetidamente até que uma expressão
booliana especificada retorne false.
18 | Lição 1
Figura 1-6
Fluxograma equivalente
do loop while de exemplo
Como você pode ver, o loop for combina as três expressões de controle essencial de uma
iteração. Isso resulta em um código mais legível. O loop for é especialmente útil para criar
iterações que devem ser executadas um número especificado de vezes.
Execute as etapas a seguir para criar um programa que use o loop for.
O loop foreach pode ser considerado uma versão aprimorada do loop for para iteração em
coleções, como matrizes e listas. A forma geral da instrução foreach é esta:
foreach (ElementType element in collection)
statement
22 | Lição 1
As expressões de controle para o loop foreach devem ser colocadas entre parênteses.
Se mais de uma instrução precisar ser executada como parte do loop, essas instruções
deverão ser colocadas juntas e entre chaves.
Execute as etapas a seguir para criar um programa que mostra como o loop foreach
fornece uma maneira simples de iterar em uma coleção.
A recursão e a iteração estão relacionadas. Você pode escrever um método que gera os
mesmos resultados usando a recursão ou a iteração. Geralmente, a natureza do problema
em si o ajudará a optar por uma solução iterativa ou recursiva. Por exemplo, uma solução
recursiva é mais elegante quando você pode definir a solução de um problema em termos
de uma versão menor do mesmo problema.
Para compreender melhor esse conceito, tomemos o exemplo da operação fatorial
de matemática. A definição recursiva geral para o fatorial n (escrito n!) é a seguinte:
1 if n = 0,
n! =
(n − 1)! × n if n > 0.
De acordo com essa definição, se o número for 0, o fatorial será um. Se o número for
maior que zero, o fatorial será o número multiplicado pelo fatorial do próximo número
Introdução à programação | 23
menor. Por exemplo, você pode dividir 3! desta forma: 3! = 3 * 2! —> 3 * 2 * 1! —> 3 *
2 * 1 * 0! —> 3 * 2 * 1 * 1 —> 6.
Execute as etapas a seguir para criar um programa que apresente uma solução recursiva
para um problema de fatorial.
Uma exceção é uma condição de erro inesperada que ocorre durante a execução de um
programa C#. Quando isso ocorre, o tempo de execução cria um objeto para representar
o erro e “lança-o”. A menos que você “capture” a exceção, escrevendo um código
de tratamento de exceção adequado, a execução do programa será encerrada.
Por exemplo, se você tentar dividir um número inteiro por zero, a exceção
DivideByZeroException será gerada. No .NET Framework, uma exceção é representada
usando um objeto da classe System.Exception ou uma de suas classes derivadas. Há
classes de exceção predefinidas que representam várias situações de erro que ocorrem
com frequência, como a DivideByZeroException mencionada anteriormente. Se estiver
criando um aplicativo que precisa gerar qualquer exceção específica do aplicativo, você
deverá criar uma classe de exceção personalizada derivada da classe System.Exception.
Tratamento de exceções
Para lidar com exceções, coloque o código que gera as exceções dentro de um bloco
try e coloque o código que lida com as exceções dentro de um bloco catch.
O exercício a seguir mostra como usar um bloco try-catch para lidar com uma exceção.
O exercício utiliza o método File.OpenText para abrir um arquivo de disco. Essa instrução
será executada sem problemas no caso normal, mas, se o arquivo (ou a permissão para ler
o arquivo) estiver ausente, uma exceção será gerada.
Usando try-catch-finally
O bloco finally é usado associado ao bloco try. O bloco finally é sempre executado,
mesmo que uma exceção seja gerada. O bloco finally é geralmente usado para
escrever um código de limpeza.
Quando uma exceção ocorre, ela geralmente significa que algumas linhas de código após
a exceção não foram executadas. Isso pode deixar seu programa em um estado instável ou
sujo. Para evitar essas situações, você pode usar a instrução finally para garantir que um
código de limpeza específico seja sempre executado. Isso pode envolver o encerramento
de conexões, a liberação de recursos ou a definição de variáveis para seus valores
esperados. Vamos examinar um bloco finally no exercício a seguir.
USAR TRY-CATCH-FINALLY
RESUMO DE HABILIDADES
■ Avaliação de conhecimento
• O .NET Framework oferece suporte ao tratamento de exceções padrão para
identificar e lidar com erros de tempo de execução. Para lidar com exceções, coloque
o código que gera as exceções dentro de um bloco try e coloque o código que lida
com as exceções dentro de um bloco catch.
• O bloco finally é usado associado ao bloco try. O bloco finally é sempre executado,
mesmo que uma exceção seja gerada. O bloco finally é geralmente usado para
escrever um código de limpeza.
Preencha as lacunas
Complete as frases a seguir com a(s) palavra(s) correta(s) nas lacunas fornecidas.
1. A instrução seleciona para execução uma lista de instruções que tem um
rótulo associado que corresponde ao valor de uma expressão.
2. O loop testa a condição no fim do loop, e não no início.
3. O único operador que usa três argumentos é o operador.
4. O loop é a maneira mais compacta de iterar nos itens de uma coleção.
5. Em um computador de 32 bits, uma variável do tipo de dados int ocupa
bytes de memória.
28 | Lição 1
Múltipla escolha
number2
d. number2
number1
4. Em uma instrução switch, se nenhuma das instruções de caso coincidir com a
expressão switch, o controle será transferido para qual instrução?
a. break
b. continue
c. default
d. return
5. Você precisa escrever um código que encerre uma conexão com um banco de dados
e precisa assegurar que esse código seja sempre executado, mesmo que ocorra ou não
uma exceção. Onde você deve escrever esse código?
a. Dentro de um bloco try
b. Dentro de um bloco catch
c. Dentro de um bloco finally
d. Dentro do método Main
6. Você precisa armazenar valores entre 0 e 255. Também precisa garantir que seu
programa minimize o uso de memória. Que tipo de dados você deve usar para
armazenar esses valores?
a. byte
b. char
c. short
d. Int
7. Se você não tiver um caso base case no seu algoritmo recursivo, crie uma recursão
infinita. Uma recursão infinita levará o programa a gerar uma exceção. Que exceção
será gerada nesse caso?
a. OutOfMemoryException
b. StackOverflowException
c. DivideByZeroException
d. InvalidOperationException
8. Você está aprendendo a desenvolver algoritmos repetitivos em C#. Escreva o seguinte
método:
private static void ForTest()
{
for(int i = 1; i < 5;)
{
Console.WriteLine(“O valor de i = {0}”, i);
}
}
Quantas repetições o loop for executará nesse código?
a. 0
b. 4
c. 5
d. Repetições infinitas
9. Qual dos seguintes recursos C# você deve usar para organizar um código e criar tipos
globalmente exclusivos?
a. Montagem
b. Namespace
30 | Lição 1
■ Avaliação da competência
c. Classe
d. Tipo de dados
10. Você escreve o seguinte trecho de código:
int[] numbers = {1, 2, 3, 4};
Quantidade < 10 S N N N
Quantidade < 50 S S N N
Quantidade < 100 S S S N
Desconto 5% 10% 15% 20%
■ Avaliação de proficiência
Qual é o valor da variável val após a execução desse trecho de código?
a. 1
b. 2
c. 3
d. 4
P R I N C I PA I S T E R M O S
modificador de acesso encapsulamento polimorfismo
acessadores eventos propriedades
classes abstratas herança tipo de referência
propriedades autoimplementadas interfaces classes seladas
classe método assinatura
construtores namespace números de estáticos
delegados objetos tipo de valor
32
Introdução à programação orientada a objeto | 33
Uma ótima maneira de começar a pensar em uma maneira orientada a objeto é observar os
objetos do mundo real, como carros, telefones, players de música etc. Você notará que todos
esses objetos têm estado e comportamento. Por exemplo, os carros não só têm vários estados
(por exemplo, nome de modelo, cor, velocidade atual, nível de combustível), mas também
diversos comportamentos (como aceleração, freio, mudança de marcha). Da mesma forma,
você perceberá que alguns objetos são simples, enquanto outros são complexos. Os objetos
mais complexos (como um carro) são constituídos por objetos menores que, por sua vez,
têm seu próprio estado e comportamento. Você notará também que, apesar de um carro ser
um objeto complexo, só é necessário conhecer alguns itens para interagir com ele. Ao dirigir
um carro, por exemplo, você simplesmente invoca um comportamento, como aceleração
ou freio; você não tem conhecimento de muitos milhares de detalhes internos do trabalho
existente sob o capô.
Um objeto de software é conceitualmente semelhante a um objeto do mundo real.
No ambiente de software, um objeto armazena seu estado em campos e expõe seu
comportamento por meio de métodos. Quando um método é chamado em um objeto, você
obtém uma funcionalidade bem-definida sem precisar se preocupar com a complexidade
interna do objeto ou com o método em si. Esse conceito de ocultar a complexidade
é denominado encapsulamento e é uma das muitas características da programação
orientada a objeto sobre a qual você aprenderá mais nesta lição.
No mundo real, os objetos precisam de um modelo que defina como eles devem ser c ompilados.
Todos os objetos criados usando o mesmo modelo têm aparência e comportamento semelhantes.
Por exemplo, imagine uma determinada marca e modelo de carro.
No mundo do software, uma classe é o modelo do qual são criados os objetos individuais.
Um objeto também é conhecido como uma instância de uma classe.
Os construtores são métodos de classe especiais executados quando uma nova instância
de uma classe é criada. Eles são usados para inicializar os membros de dados do objeto.
Eles devem ter exatamente o mesmo nome da classe e não têm um tipo de retorno. Vários
construtores, cada um com uma assinatura exclusiva, podem ser definidos para uma classe.
Um construtor que não usa argumentos é denominado construtor padrão. Se uma classe for
definida sem qualquer construtor, um construtor padrão invisível que não tem absolutamente
nenhuma função será automaticamente gerado.
Muitas vezes, é útil ter construtores adicionais para fornecer outras maneiras de inicializar um
objeto. A classe Rectangle, definida anteriormente, é apenas uma maneira de criar e inicializar
seu objeto: chamando o construtor que aceita dois parâmetros, ambos do tipo de dados padrão.
CRIANDO OBJETOS
CRIAR UM OBJETO
PREPARE-SE. Para esta atividade, use o projeto de aplicativo de console (Lesson 02) que
você criou no exercício anterior. Em seguida, execute estas etapas:
1. Modifique o código da classe Program para:
class Program
{
static void Main(string[] args)
{
Rectangle rect = new Rectangle(10.0, 20.0);
double area = rect.GetArea();
Console.WriteLine(“Área do retângulo: {0}”,
area);
}
}
2. Selecione Depurar > Iniciar sem Depuração. Uma janela de console exibirá a área do
retângulo.
3. SALVE seu projeto.
PAUSE. Deixe o projeto aberto para ser usado no próximo exercício.
A classe Rectangle fornece apenas uma única maneira de construir uma instância da classe:
chamando um construtor com dois argumentos do tipo de dados double. Aqui, você pode
criar um objeto usando a palavra-chave new seguida pela chamada do construtor de classe
apropriado.
36 | lição 2
Quando o código for executado, um objeto do tipo Rectangle será criado na memória
TOME NOTA
* heap. Uma referência a essa memória é armazenada dentro da variável rect, e a variável
As classes e os objetos rect é armazenada na pilha. Posteriormente neste bloco de código, você poderá usar rect
são diferentes. Uma para manipular e se referir ao objeto recém-criado.
classe define o modelo
de um objeto, mas não O uso da referência do objeto permite que você acesse os membros de classe. Por exemplo,
é um objeto. Por outro o código chama o método GetArea no objeto, e o valor retornado pelo método é armazenado
lado, um objeto é uma na área variável. Os campos de dados, length e width, do objeto rect não são acessíveis aqui,
instância concreta de pois estão marcados como private na definição de classe.
uma classe, mas não
é uma classe. NOÇÕES BÁSICAS SOBRE PROPRIEDADES
As propriedades permitem que você acesse dados de classe com segurança e flexibilidade.
TOME NOTA
* As propriedades são membros de classe que podem ser acessados como campos de dados,
As propriedades
são muitas vezes mas contêm código, como um método. Em geral, as propriedades são utilizadas para
chamadas de campos expor os campos de dados de uma classe de uma maneira mais controlada. Por exemplo,
“inteligentes”, pois um campo private pode ser exposto por meio de uma propriedade public, mas não
podem incluir código é necessário usar propriedades dessa maneira.
para verificar a Uma propriedade tem dois acessadores, get e set. O acessador get é usado para
consistência ou a retornar o valor de propriedade, e o acessador set é usado para atribuir um novo valor
validade dos dados. à propriedade. Uma propriedade é muitas vezes definida como public e, por convenção,
sempre tem um nome que começa com letra maiúscula. Em contraste, a convenção de
nomeação dos campos de dados private consiste em iniciar com letra minúscula.
CRIAR PROPRIEDADES
USE o projeto que você salvou no exercício anterior. Em seguida, execute as seguintes tarefas:
1. Modifique o código da classe Rectangle como mostrado abaixo. Nesse código,
o construtor é removido e duas propriedades são inseridas:
class Rectangle
{
private double length;
private double width;
public double Length
{
get
{
return length;
}
set
{
if ( value > 0.0)
length = value;
}
}
public double Width
{
get
{
return width;
}
Introdução à programação orientada a objeto | 37
set
{
if ( value > 0.0)
width = value;
}
}
public double GetArea()
{
return length * width;
}
}
2. Em seguida, modifique o código da classe Program para:
class Program
{
static void Main(string[] args)
{
Rectangle rect = new Rectangle();
rect.Length = 10.0;
rect.Width = 20.0;
double area = rect.GetArea();
Console.WriteLine(
“Área do retângulo: {0}”, area);
}
}
3. Selecione Depurar > Iniciar sem Depuração. Uma janela de console exibirá a área do
retângulo.
4. SALVE seu projeto.
PAUSE. Deixe o projeto aberto para ser usado no próximo exercício.
TOME NOTA
* Nesse exercício, você modificou a classe Rectangle para introduzir duas propriedades,
O padrão de Length e Width. As propriedades são muitas vezes definidas com um modificador de
programação normal acesso public. No código para a propriedade Length, o acessador get simplesmente retorna
é que todos os campos o valor do campo de dados length. No entanto, o acessador set verifica o valor atribuído
de dados de uma classe (usando a palavra-chave value) à propriedade e modificará o campo de dados length
sejam declarados apenas se o valor for positivo. Os campos privados length e width também são chamados
como private, e que campos de suporte para as propriedades que respectivamente os expõem.
o acesso a esses A classe Rectangle também não declara qualquer construtor explícito. Nesse caso, os
campos privados usuários da classe (o método Main) precisam usar o construtor padrão e depender das
seja feito através de propriedades para inicializar os dados de classe.
propriedades públicas
que verifiquem os O método Main usa as propriedades Length e Width para definir os dados do objeto rect.
valores dos dados para A tentativa de definir Length ou Width para um valor negativo será ignorada e, nesse
fins de validade. caso, os campos de dados continuarão mantendo seu valor original 0.
Ao definir propriedades, você pode excluir o acessador set ou get. Se não incluir um
acessador set, você não permitirá definir o valor da propriedade e, como resultado, terá uma
propriedade somente leitura. Por outro lado, se não incluir o acessador get, você não poderá
obter o valor da propriedade e, como resultado, terá uma propriedade somente gravação.
A palavra-chave this pode ser usada para acessar membros a partir de construtores,
métodos de instância e acessadores de propriedades de instância.
Introdução à programação orientada a objeto | 39
A palavra-chave this é uma referência à instância atual da classe. Você pode usar a
palavra-chave this para se referir a qualquer membro do objeto atual. Por exemplo,
no início deste capítulo, a classe Rectangle foi escrita desta forma:
class Rectangle
{
private double length;
private double width;
public Rectangle(double l, double w)
{
length = l;
width = w;
}
public double GetArea()
{
return length * width;
}
}
No entanto, ela poderia ter sido escrita assim:
class Rectangle
{
private double length;
private double width;
public Rectangle(double l, double w)
{
this.length = l;
this.width = w;
}
public double GetArea()
{
return this.length * this.width;
}
}
Como você pode ver, no segundo exemplo, a palavra-chave this foi usada dentro do
construtor e do método GetArea para se referir aos campos de dados do objeto atual
da classe Rectangle. Embora não tenha sido necessário usar a palavra-chave this nesse
TOME NOTA
* caso, sua utilização fornece mais flexibilidade na nomeação dos parâmetros de método.
Em C#, os caracteres Por exemplo, você poderia definir o construtor da seguinte forma:
// são usados para public Rectangle(double length, double width)
adicionar comentários
{
de linha única ao
código. O texto após os // o comprimento e a largura dos nomes de parâmetros
caracteres // é ignorado // cobrem o comprimento e a largura dos membros de classe
pelo compilador. Os // neste escopo
comentários de várias this.length = length;
linhas começam com os this.width = width;
caracteres /* e terminam
com os caracteres */. }
Dentro do escopo da definição do construtor Rectangle, os nomes length e width agora
se referirão ao parâmetro que está sendo passado. Os nomes dos campos de dados foram
sombreados e só podem ser acessados usando a palavra-chave this.
40 | lição 2
Delegados são tipos especiais usados para encapsular um método com uma
assinatura específica.
Os delegados são objetos especiais que podem conter uma referência a um método com
uma assinatura específica. Um delegado é definido usando a palavra-chave delegate.
Por exemplo, você pode definir um delegado da seguinte forma:
public delegate void RectangleHandler(Rectangle rect);
A definição de delegado especifica a assinatura do método cuja referência pode ser
armazenada por um objeto delegate. Por exemplo, no código acima, você define um
delegado RectangleHandler que pode conter referências a um método que retorna void
e aceita um único parâmetro do tipo Rectangle.
Portanto, se você tiver um método com uma assinatura semelhante, ele será um candidato
ideal para ser atribuído a uma instância delegate. Por exemplo:
public void DisplayArea(Rectangle rect)
{
Console.WriteLine(rect.GetArea());
}
O tipo de delegado pode ser usado para declarar uma variável que pode se referir a
qualquer método com a mesma assinatura do delegado. Por exemplo, você pode dizer:
RectangleHandler handler;
E, em seguida, pode atribuir o método ao delegado usando esta sintaxe:
handler += new RectangleHandler(DisplayArea);
Se preferir, você poderá usar a sintaxe de atalho mostrada abaixo:
handler += DisplayArea;
Observe que a sintaxe usa a operação de adição. Isso significa que você pode associar
mais de um método (de assinatura compatível), criando, assim, uma lista de invocação
de um ou mais métodos.
Finalmente, uma chamada para um delegado pode ser feita por uma sintaxe de chamada
de método, como esta:
Rectangle rect = new Rectangle (10, 20);
handler(rect);
Quando o delegado é chamado dessa forma, ele invoca todos os métodos em sua lista de
invocação. Neste exemplo específico, o objeto handler se refere apenas a um método DisplayArea,
e portanto, o método DisplayArea será invocado com o objeto rect como parâmetro.
Entre várias outras aplicações, os delegados formam a base das declarações de evento,
conforme será discutido na próxima seção.
NOÇÕES BÁSICAS SOBRE EVENTOS
Os eventos são uma maneira de uma classe notificar outras classes ou objetos quando
algo de interesse ocorre. A classe que envia a notificação é chamada de editor do
evento. A classe que recebe a notificação é chamada de assinante do evento.
Os eventos são fáceis de serem compreendidos no contexto de uma GUI (interface gráfica
do usuário). Por exemplo, quando um usuário clica em um botão, ocorre um evento
Click. Vários elementos de interface do usuário podem se inscrever nesse evento e alterar
Introdução à programação orientada a objeto | 41
seu estado visual apropriadamente (por exemplo, alguns controles são habilitados ou
desabilitados). Nesse tipo de comunicação de evento, os editores de eventos não precisam
saber quais objetos se inscreverão nos eventos que estão sendo gerados.
Os eventos não são limitados apenas à programação da GUI. Na verdade, os eventos
desempenham um papel importante nas bibliotecas de classes do .NET Framework como
uma maneira de os objetos sinalizarem qualquer mudança em seu estado. Você trabalhará
com eventos em praticamente todos os programas.
Ao definir os eventos, você geralmente precisa de duas informações:
• Um delegado que conecte o evento ao seu(s) método(s) handler
• Uma classe que contenha os dados do evento. Em geral, essa classe é derivada da
classe EventArgs
Para definir um evento, você pode usar um delegado personalizado. No entanto, na maioria
dos casos, se o seu evento não tiver dados específicos de evento, a utilização do delegado
predefinido EventHandler será suficiente. O delegado EventHandler é definido desta forma:
public delegate void EventHandler(Object sender, EventArgs e);
Aqui, o parâmetro sender é uma referência ao objeto que gera o evento, e o parâmetro
e é uma referência a um objeto de dados event que não contém dados do evento.
A classe EventArgs é usada pelos eventos que não passam quaisquer informações relacionadas
ao evento para um manipulador de eventos quando um evento é gerado. Se o manipulador
de eventos necessitar de informações relacionadas ao evento, o aplicativo deverá derivar uma
classe da classe EventArgs para armazenar os dados relacionados ao evento.
PUBLICAR E INSCREVER-SE EM EVENTOS
USE o projeto que você salvou no exercício anterior para executar as tarefas a seguir:
1. Modifique o código da classe Rectangle como mostrado abaixo:
class Rectangle
{
public event EventHandler Changed;
private double length;
public double Length
{
get
{
return length;
TOME NOTA
* }
O campo EventArgs. set
Empty representa um {
evento sem dados de length = value;
evento. Esse campo Changed(this, EventArgs.Empty);
equivale a ter uma
}
instância somente leitura
da classe EventArgs. }
}
2. Modifique o código da classe Program para:
class Program
{
static void Main(string[] args)
{
Rectangle r = new Rectangle();
42 | lição 2
Um namespace permite que você organize o código e crie nomes de classe exclusivos.
and
namespace CompanyB
{
public class Widget { … }
}
Aqui, a classe do namespace CompanyA pode ser excepcionalmente referida pelo seu
nome de classe totalmente qualificado CompanyA.Widget, enquanto o outro Widget pode
ser identificado exclusivamente como CompanyB.Widget.
O .NET Framework usa namespaces para organizar liberalmente todas as suas classes.
Por exemplo, o namespace System agrupa todas as classes fundamentais. O namespace
System.Data organiza as classes para acesso a dados. O namespace System.Web é usado
para as classes relacionadas à Web.
É evidente que, com o uso de namespaces, você pode acabar tendo nomes de classe
totalmente qualificados realmente longos que podem resultar em programas detalhados
e muita digitação. C# resolve esse inconveniente através da diretiva using. Você pode usar
a diretiva using na parte superior do arquivo de classe desta forma:
using System.Text;
Após incluir a diretiva using para um namespace, você não precisará qualificar totalmente
as classes desse namespace no arquivo.
Os membros de classe discutidos até este momento nesta seção (por exemplo, campos de
dados, métodos e propriedades) operam todos em objetos individuais. Esses membros são
chamados como membros de instância por poderem ser usados apenas depois que uma
instância de uma classe for criada. Por outro lado, a palavra-chave static é usada para declarar
os membros que não pertencem a objetos individuais, mas a uma classe. Esses membros de
classe são chamados como membros estáticos. Um exemplo comum de um membro estático
é o método familiar Main que serve como ponto de entrada para o seu programa.
USE o projeto que você salvou no exercício anterior. Em seguida, execute as seguintes etapas:
1. Modifique o código da classe Rectangle como mostrado abaixo:
class Rectangle
{
public static string ShapeName
{
get { return “Rectangle”; }
}
public double Length { get; set; }
public double Width { get; set; }
public double GetArea()
{
return this.Length * this.Width;
}
}
44 | lição 2
Um tipo de valor armazena dados diretamente na própria memória. Por outro lado,
os tipos de referência armazenam apenas uma referência a um local de memória;
aqui, os dados reais são armazenados no local de memória que está sendo referenciado.
A maioria dos tipos de dados elementares internos (como bool, int, char, double etc.)
são tipos de valor. Os tipos de dados definidos pelo usuário criados com a palavra-chave
struct também são tipos de valor. Os tipos de referência incluem os tipos criados com
as palavras-chave object, string, interface, delegate e class.
Noções básicas sobre structs
A palavra-chave struct é usada para criar tipos definidos pelo usuário que consistem
em pequenos grupos de campos relacionados. Os structs são tipos de valor — ao
contrário das classes, que são tipos de referência.
são tipos de valor, ao passo que as classes são tipos de referência. Ao contrário de uma
TOME NOTA
* classe, o struct não pode ser herdado de outra classe ou struct.
Os structs são
principalmente usados Noções básicas sobre alocação de memória
para criar tipos simples.
Se você estiver criando
Após inserir um valor ou um texto em uma célula, você poderá modificá-lo de várias
um struct muito
maneiras. Em particular, você pode remover o conteúdo completamente, inserir um
complexo, considere
valor diferente para substituir o conteúdo anterior ou alterar o que digitou.
o uso de uma classe.
Uma boa maneira de compreender como os tipos de valor diferem dos tipos de referência
é visualizar como cada um deles é representado na memória. A figura 2-1 mostra como
os tipos de valor são criados na memória. Quando você cria uma variável do tipo int, por
exemplo, um local de memória nomeado é criado e você pode usá-lo para armazenar um
valor do tipo int. Inicialmente, quando você não atribui um valor explicitamente, o valor
padrão do tipo de dados (para int, o valor padrão é 0) é armazenado no local de memória.
Em seguida, quando uma atribuição for feita, o endereço de memória identificado pelo nome
da variável será atualizado com o novo valor (10 no caso da atribuição da figura 2-1).
Figura 2-1
Exibição do código Exibição da memória
Visualizando um tipo de
valor na memória number
int number; 0
number
number = 10; 10
Agora, examine a figura 2-2, que mostra um tipo de referência — especificamente, o tipo
de dados string. Quando você cria uma variável do tipo string, um local de memória é
criado e será identificado por esse nome. No entanto, esse local de memória não conterá
o conteúdo da cadeia de caracteres. Nesse caso, essa variável armazenará o endereço
de memória (uma referência) do local em que a cadeia de caracteres está realmente
armazenada.
Figura 2-2
Exibição do código Memory view
Visualizando um tipo de
referência na memória name
name
Inicialmente, quando nenhum valor é atribuído, a variável tem o valor null (uma r eferência
nula; em outras palavras, essa variável não faz referência a um endereço de memória válido).
Em seguida, na próxima instrução, quando você diz:
name = “Northwind”;
A cadeia de caracteres “Northwind” é criada em um local de memória específico (para
simplificar, suponha que o endereço de memória seja m100), e esse endereço de memória
é armazenado no nome de variável. Posteriormente, no momento de recuperar o valor do
46 | lição 2
nome da variável, o tempo de execução saberá que seu conteúdo não está armazenado na
variável, mas no local de memória apontado pela variável.
USE o projeto que você salvou no exercício anterior para executar as etapas a seguir:
1. Adicione o código a seguir após a definição da classe Rectangle para criar um struct
Point:
struct Point
{
TOME NOTA
* public double X, Y;
É possível criar um }
struct sem usar o
operador new. Você 2. Modifique o código do método Main como mostrado abaixo:
pode simplesmente static void Main(string[] args)
dizer Point p1; para
criar uma variável do {
tipo struct. Point p1 = new Point();
p1.X = 10;
p1.Y = 20;
Point p2 = p1;
p2.X = 100;
Console.WriteLine(“p1.X = {0}”, p1.X);
Rectangle rect1 = new Rectangle
{ Length = 10.0, Width = 20.0 };
Rectangle rect2 = rect1;
TOME NOTA
* rect2.Length = 100.0;
Quando você copia
Console.WriteLine(“rect1.Length = {0}”,
uma variável de tipo
de referência para rect1.Length);
outra variável do }
mesmo tipo, apenas
as referências são 3. Selecione Depurar > Iniciar sem Depuração. Uma janela de console será exibida
copiadas. Como mostrando os valores de p1.X e rect1.Length.
resultado, após 4. SALVE seu projeto.
a cópia, as duas PAUSE. Deixe o projeto aberto para ser usado no próximo exercício.
variáveis apontarão
para o mesmo objeto. Aqui, a primeira parte do programa cria uma cópia do tipo de valor Point, e a segunda
metade cria uma cópia do tipo de referência Rectangle.
Vamos começar analisando como a cópia de um tipo de valor é feita. Para começar,
quando a instrução a seguir for executada, uma nova variável p2 será criada na memória,
e seu conteúdo será copiado a partir da variável p1:
Point p2 = p1;
Após a execução dessa instrução, a variável p2 será criada, e o conteúdo da variável p1
será copiado para a variável p2. Tanto p1 quanto p2 têm seu próprio conjunto de valores
disponíveis em seus respectivos locais de memória. Portanto, quando a instrução a seguir
for executada:
p2.X = 100;
Ela só afetará o valor de X correspondente ao local de memória da variável p2. O valor de
X para a variável p1 permanece inalterado.
Introdução à programação orientada a objeto | 47
Agora, vamos analisar como a cópia funciona entre os tipos de referência. Nesse caso,
quando a instrução a seguir for executada, uma nova variável rect2 será criada e, assim
como antes, o conteúdo de rect1 será copiado para o local de memória de rect2:
Rectangle rect2 = rect1;
Entretanto, como a classe Rectangle é um tipo de referência, o conteúdo da variável rect1
é, na verdade, uma referência a um local de memória que contém um objeto Rectangle.
Portanto, após a inicialização acima, tanto rect1 quanto rect2 apontarão para o mesmo
local de memória e, por sua vez, para o mesmo objeto Rectangle. Em outras palavras,
há apenas um objeto rectangle na memória, e tanto rect1 quanto rect2 estão se referindo
a ele. A próxima instrução modifica o comprimento do objeto rectangle:
rect2.Length = 100.0;
PRONTO PARA Essa instrução faz referência ao local de memória apontado por rect2 (que passa a ser o
CERTIFICAÇÃO
mesmo local de memória apontado por rect1) e modifica o comprimento do objeto Rectangle.
Você compreende
Agora, se tentar fazer referência ao mesmo local de memória através do objeto rect1, você
o que são tipos de
obterá o objeto modificado e o código a seguir exibirá o valor “rect1.Length = 100”:
dados e alocação de
memória? Console.WriteLine(“rect1.Length = {0}”,
1,1 rect1.Length);
✚ MAIS INFORMAÇÕES
A memória aloca ocorre sempre nos objetos no heap. O heap é a memória disponível para um
programa em tempo de execução para alocação de memória dinâmica. Por outro lado, alguns itens
de dados podem ser criados na pilha de execução ou na pilha de chamadas. Os itens criados na pilha
são os parâmetros de método e as variáveis locais declaradas dentro de um método. A memória
da pilha é recuperada quando a pilha é esvaziada (quando um método retorna, por exemplo).
A memória alocada no heap é automaticamente recuperada pelo coletor de lixo quando os objetos
não estão mais em uso (ou seja, nenhum outro objeto está armazenando uma referência a ele).
TOME NOTA
* Os modificadores de acesso controlam onde um tipo ou um membro de tipo pode ser usado.
Você deve usar o nível
de acesso mais restritivo Todos os tipos e os membros de tipo têm um nível de acesso que especifica onde essa
que faça sentido para classe ou seus membros podem ser usados no seu código. O nível de acesso pode ser
um membro de tipo. definido usando um dos modificadores de acesso especificados na tabela 2-1.
Tabela 2-1
Modificadores de acesso
Suponha que queremos criar um conjunto de classes que descreva polígonos, como
TOME NOTA
* retângulos ou triângulos. Essas classes terão algumas propriedades comuns, como
Diferentemente das largura e comprimento. Para esse caso, você pode criar uma classe base Polygon com as
classes, os structs propriedades Width e Length, e as classes derivadas Rectangle e Triangle herdarão essas
não oferecem suporte propriedades ao fornecerem sua própria funcionalidade. O exercício a seguir explica esse
à herança. conceito em mais detalhes.
USE o projeto que você salvou no exercício anterior para executar as ações a seguir:
1. Adicione uma nova classe denominada Polygon como mostrado abaixo:
class Polygon
{
public double Length { get; protected set; }
public double Width { get; protected set; }
}
4. Selecione Depurar > Iniciar sem Depuração. Uma janela de console será exibida
mostrando a largura, o comprimento e a área do retângulo.
5. SALVE seu projeto.
PAUSE. Deixe o projeto aberto para ser usado no próximo exercício.
Para definir uma classe derivada, você pode colocar dois-pontos após o nome da classe
derivada, seguido do nome da classe base. Aqui, a classe Polygon é a classe base da classe
Rectangle.
50 | lição 2
As classes abstratas fornecem uma definição comum de uma classe base que pode
ser compartilhada por várias classes derivadas. Por outro lado, as classes seladas
fornecem funcionalidade completa, mas não podem ser usadas como classes base.
No exercício anterior, você definiu um método GetArea na classe Rectangle. Suponha que
você queira criar outra classe, Triangle, que seja do tipo Polygon. Aqui, você precisará de
um método GetArea na classe Triangle que calculará a área de um triângulo.
Muitas vezes, as classes base funcionam como repositório da funcionalidade comum.
No caso de Polygon, o polígono não saberá como calcular a área sem o conhecimento
do tipo de forma. Mas, em geral, espera-se que todas as classes do tipo Polygon sejam
capazes de calcular sua área. Essas expectativas podem ser passadas para a classe base
com a ajuda de uma palavra-chave abstract.
CRIAR CLASSES ABSTRATAS
USE o projeto que você salvou no exercício anterior e execute as etapas a seguir.
1. Modifique a classe Polygon como mostrado abaixo:
abstract class Polygon
{
public double Length { get; protected set; }
public double Width { get; protected set; }
abstract public double GetArea();
}
2. Modifique a classe Rectangle como mostrado abaixo:
class Rectangle: Polygon
{
public Rectangle(double length, double width)
{
Length = length;
Width = width;
}
public override double GetArea()
{
return Width * Length;
}
}
3. Observe que nenhuma modificação no método Main é necessária.
4. Selecione Depurar > Iniciar sem Depuração. Uma janela de console será exibida
mostrando a largura, o comprimento e a área do retângulo.
5. SALVE seu projeto.
PAUSE. Deixe o projeto aberto para ser usado no próximo exercício.
Introdução à programação orientada a objeto | 51
No entanto, você não precisa declarar a classe Polygon na última maneira, pois a herança
da classe Object é assumida implicitamente. Como parte dessa herança, uma classe
derivada pode substituir os métodos da classe Object. Dois dos métodos mais comuns
para isso são:
• Equals: oferece suporte à comparação entre dois objetos e retornará true se os dois
objetos tiverem o mesmo valor.
• ToString: retorna uma representação de cadeia de caracteres da classe. Por padrão,
ele retorna o nome completo da classe. Muitas vezes, é útil substituir esse método
para que ele retorne uma representação de cadeia de caracteres do estado atual do
objeto.
O exemplo a seguir mostra como você pode substituir o método ToString na classe
Rectangle:
class Rectangle: Polygon
{
public Rectangle(double length, double width)
{
Length = length;
Width = width;
}
public override double GetArea()
{
return Width * Length;
}
public override string ToString()
{
return String.Format(
“Width = {0}, Length = {1}”,
Width, Length);
}
}
As classes derivadas têm uma relação “é um” com sua classe base. Por exemplo,
podemos dizer que Rectangle é um Polygon. Assim, um objeto da classe Rectangle tem
efetivamente dois tipos de dados neste caso: o objeto é um Rectangle, e o objeto também
é um Polygon.
Em C#, o tempo de execução permite que você converta um objeto em sua classe ou
em qualquer uma de suas classes base. Por exemplo, você pode dizer:
Polygon p = new Rectangle(10, 20);
Aqui, um novo objeto Rectangle é criado e é convertido em seu tipo base Polygon.
C# não exige qualquer sintaxe especial para isso, pois a conversão em um tipo base
é considerada uma conversão segura.
Introdução à programação orientada a objeto | 53
A conversão também é possível do modo contrário. Por exemplo, você pode dizer:
Object o = new Rectangle(10, 20);
…
Rectangle r = (Rectangle) o;
Aqui, um objeto Rectangle é atribuído primeiro a um Object (a classe base definitiva)
e, em seguida, o objeto resultante é convertido de volta como um Rectangle. Quando
a última atribuição acontece, uma conversão explícita é necessária, pois você está
convertendo um objeto mais geral em um objeto menos geral. O tempo de execução
verifica se o valor da variável o é compatível com a classe Rectangle. Se, no tempo de
execução o valor de o não for compatível com a classe Rectangle, o tempo de execução
gerará System.InvalidCastException.
USANDO O OPERADOR IS
Para evitar erros de tempo de execução, como InvalidCastException, o operador is
pode ser usado para verificar se a conversão é permitida antes de realmente executar
a conversão, como neste exemplo:
if (o is Rectangle)
{
Rectangle r = (Rectangle) o;
}
TOME NOTA
* Aqui, o tempo de execução verifica o valor do objeto o. Em seguida, a instrução de
Se estiver usando
conversão somente será executada se o contiver um objeto Rectangle.
o operador as para
converter um tipo, você
USANDO O OPERADOR AS
não precisará verificar o
operador is. Você poderá Outro operador de conversão útil é as. O operador as é semelhante à operação de
simplesmente verificar conversão, mas, no caso de as, se a conversão de tipo não for possível, null será retornado,
o valor de retorno em em vez de gerar uma exceção. Por exemplo, considere o código a seguir:
relação a nulo. Rectangle r = o as Rectangle;
if (r != null)
{
PRONTO PARA // fazer alguma coisa
CERTIFICAÇÃO
}
Você compreende o
significado de herança? Se, no tempo de execução, não for possível converter o valor da variável o em um
2,2 retângulo, um valor null será atribuído à variável r. Nenhuma exceção será gerada.
Você está desenvolvendo um aplicativo que permite que os usuários trabalhem com
diferentes tipos de polígonos. Você tem uma coleção que contém vários tipos de
polígonos, como um retângulo, um triângulo e um quadrado. Cada polígono fornece sua
própria implementação do método Draw. Ao trabalhar com essa coleção, você não sabe
54 | lição 2
exatamente com qual forma está trabalhando, mas deseja que o método Draw correto seja
sempre invocado. O polimorfismo permite que você faça exatamente isso.
Ele permite que os objetos de uma classe derivada sejam tratados em tempo de execução
como objetos da classe base. Quando um método é invocado em tempo de execução,
o seu tipo exato é identificado, e o método apropriado é invocado da classe derivada.
USAR O POLIMORFISMO
USE o projeto que você salvou no exercício anterior para executar as etapas a seguir:
1. Modifique a classe Polygon como mostrado abaixo:
class Polygon
{
public virtual void Draw()
{
Console.WriteLine(“Drawing: Polygon”);
}
}
Quando uma classe base define um membro virtual, a classe derivada pode lidar com isso
de duas maneiras: especificamente, a classe derivada pode usar a palavra-chave override
ou new. A palavra-chave override tem prioridade sobre a definição de classe base do
membro. Aqui, o objeto de classe derivada chamará o membro substituído em vez do
membro de classe base.
Em comparação, se a palavra-chave new for usada, uma nova definição do membro
será criada e o membro de classe base será oculto. No entanto, se a classe derivada for
convertida em uma instância da classe base, os membros ocultos da classe ainda poderão
ser chamados.
56 | lição 2
A classe System.Object fornece um método ToString. Por convenção, você deve usar
esse método para retornar a representação compreendida pelo usuário para uma classe.
TOME NOTA
* Ao criar seus tipos, é recomendável que você substitua esse método para retornar
informações legíveis sobre os objetos.
As interfaces são usadas para estabelecer contratos através dos quais os objetos podem
O RESULTADO interagir entre si sem conhecer os detalhes da implementação.
Como IComparable decide como comparar dois objetos Rectangle ou dois objetos
Employee? Ele não decide. As classes interessadas nessas comparações devem
implementar a interface IComparable, fornecendo um corpo de método para o método
CompareTo. Cada classe que implementa IComparable é livre para fornecer sua própria
lógica de comparação personalizada dentro do método CompareTo.
USE o projeto que você salvou no exercício anterior para executar as etapas a seguir:
1. Modifique a classe Rectangle como mostrado abaixo:
class Rectangle: Polygon, IComparable
{
public double Length { get; set; }
public double Width { get; set; }
public override void Draw()
{
Console.WriteLine(“Drawing: Rectangle”);
}
public double GetArea()
{
return Length * Width;
}
public int CompareTo(object obj)
{
if (obj == null)
return 1;
if (!(obj is Rectangle))
throw new ArgumentException();
Rectangle target = (Rectangle)obj;
double diff = this.GetArea() - target.GetArea();
58 | lição 2
if (diff == 0)
return 0;
else if (diff > 0)
return 1;
else return -1;
}
}
3. Em seguida, modifique o método Main, conforme mostrado abaixo:
static void Main(string[] args)
{
Rectangle rect1 = new Rectangle
{ Length = 10, Width = 20 };
Rectangle rect2 = new Rectangle
{ Length = 100, Width = 200 };
Console.WriteLine(rect1.CompareTo(rect2));
}
4. Selecione Depurar > Iniciar sem Depuração. Uma janela de console será exibida
mostrando o valor – 1, pois a área de rect1 é menor do que a área de rect2.
5. SALVE seu projeto.
Aqui, a classe Rectangle deriva da classe Polygon e implementa a interface IComparable.
Uma classe que implementa uma interface deve implementar todos os métodos declarados
nessa interface.
Uma interface é semelhante a uma classe abstrata, mas existem algumas diferenças
perceptíveis. Por um lado, uma classe abstrata fornece implementação incompleta, ao
passo que uma interface não fornece nenhuma implementação. Uma classe também pode
implementar várias interfaces, mas está limitada a herdar de apenas uma única classe base.
Então, como decidir se você deve usar uma interface ou uma classe abstrata? Uma
PRONTO PARA maneira é verificar se existe uma relação “é um” entre os dois conceitos. Por exemplo,
C ERTIFICAÇÃO se existir uma relação de herança entre um SalariedEmployee e um Employee, você
Você compreende poderá usar uma classe abstrata para padronizar a funcionalidade comum entre as
o que significa classes derivadas. Por outro lado, não há nenhuma relação “é um” entre um Employee
encapsulamento? e o IComparable. Portanto, a melhor forma de implementar a funcionalidade de
2,4
comparação é como uma interface.
RESUMO DE HABILIDADES
■ Avaliação de conhecimento
Preencha as lacunas
Complete as sentenças a seguir com a(s) palavra(s) correta(s) nas lacunas fornecidas.
1. Um(a) __________ é um plano gráfico de um objeto.
2. Uma classe que não fornece uma implementação completa deve ser declarada com
a palavra-chave __________.
3. As classes que desejam dar suporte à comparação devem implementar a interface
IComparable e fornecer um corpo para o método __________.
4. Você pode usar o operador __________ para verificar se ele é válido para converter
um tipo em outro.
60 | Lição 2
5. Qual dos seguintes elementos de classe a seguir você deve usar para definir
o comportamento de uma classe?
a. Método
b. Propriedade
c. Evento
d. Delegado
6. Você está escrevendo um código para uma classe denominada Product. Você
precisa ter certeza de que os membros de dados da classe serão inicializados para
seus valores corretos assim que criar um objeto da classe Product. O código de
inicialização deve ser sempre executado. O que você deve fazer?
a. Criar um método estático na classe Product para inicializar os membros de dados
b. Criar um construtor na classe Product para inicializar os membros de dados
c. Criar uma propriedade estática na classe Product para inicializar os membros de dados
d. Criar um evento na classe Product para inicializar os membros de dados
7. Você está criando uma nova classe denominada Square que é derivada da classe
Polygon. A classe Polygon tem o seguinte código:
class Polygon
{
public virtual void Draw()
{
// código adicional. . .
}
}
O método Draw na classe Square deve fornecer nova funcionalidade, mas também
ocultar a implementação da classe Polygon do método Draw. Qual segmento de
código você deve usar para realizar essa tarefa?
a. class Square: Polygon
{
public override void Draw()
{
// código adicional. . .
}
}
b. class Square: Polygon
{
public new void Draw()
{
// código adicional. . .
}
}
c. class Square: Polygon
{
public virtual void Draw()
{
// código adicional. . .
}
}
62 | Lição 2
■ Avaliação da competência
Cenário 2-1: criando propriedades
Você precisa criar uma classe denominada Product que representa um produto. A classe tem
uma única propriedade denominada Name. Os usuários da classe Product devem ser capazes
de obter e também definir o valor da propriedade Name. No entanto, qualquer tentativa de
definir o valor de Name para uma cadeia de caracteres vazia ou um valor nulo deve gerar
uma exceção. Além disso, os usuários da classe Product não devem ser capazes de acessar
nenhum outro membro de dados da classe Product. Como você criará essa classe?
■ Avaliação de proficiência
Cenário 2-1: substituindo o método ToString
Suponha que você esteja escrevendo um código para uma classe Product. A classe Product
contém o nome e o preço de um produto. Você precisa substituir o método ToString
da classe base (System.Object) para fornecer informações sobre os objetos da classe
de produto para o código de chamada. Qual código você precisa escrever para a classe
Product a fim de atender a esse requisito?
PRINCIPAIS TERMOS
teste de aceitação teste de integração teste de software
ALM (gerenciamento do ciclo de lista vinculada algoritmos de classificação
vida do aplicativo) QuickSort pilha
matrizes fila teste de sistema
teste caixa preta teste de regressão teste de unidade
Bubblesort gerenciamento de lançamento teste caixa branca
estruturas de dados análise de requisitos
processo de design desenvolvimento de software
65
66 | lição 3
Manutenção Design
Testes Desenvolvimento
Nesta seção, você aprenderá sobre as diferentes atividades e funções envolvidas em cada
estágio do processo ALM.
O ciclo de vida do aplicativo inicia quando é identificada a necessidade de um novo
aplicativo de software. Em geral, um gerente comercial é o patrocinador do projeto.
Ele ou ela analisa a necessidade, verifica como o projeto se encaixa na estratégia geral
do negócio, organiza o financiamento e inicia o processo de recrutamento para o projeto.
Um gerente de projeto provavelmente é a primeira pessoa contratada pelo gerente
comercial. O gerente de projeto é responsável pela execução geral do projeto. Suas
principais responsabilidades são garantir que o projeto permaneça dentro do orçamento
e seja concluído dentro do prazo. O gerente de projeto também é responsável pela
contratação de membros da equipe e por facilitar a cooperação dentro da equipe.
A análise de requisitos é uma das etapas mais importantes do ciclo de vida do aplicativo.
Requisitos precisos, completos e bem-documentados são essenciais para o sucesso do
projeto. Esses requisitos podem ser funcionais ou não funcionais. Os requisitos funcionais
especificam exatamente o que o sistema está projetado para realizar. Por outro lado,
os requisitos não funcionais são requisitos de qualidade, como escalabilidade, segurança,
confiabilidade etc.
Um analista de negócios é responsável por analisar as necessidades comerciais e convertê-
las em requisitos que possam ser executados pela equipe de desenvolvimento.
O processo de design gera especificações técnicas detalhadas que serão usadas para
desenvolver o sistema. A saída do processo de design é um conjunto de modelos técnicos
e especificações que fornecem orientação para os desenvolvedores e outros membros da
equipe durante a atividade de desenvolvimento do software. A saída do processo de design
é mais abstrata do que concreta. Neste momento, não há nenhum sistema real com o qual
você possa interagir.
Alguns dos participantes mais importantes neste estágio do processo ALM incluem um
arquiteto e um designer de experiência do usuário:
• Arquiteto: um arquiteto projeta o plano gráfico técnico do sistema. Isso inclui
a identificação de componentes e serviços, seu comportamento e como eles
interagem entre si e com o mundo externo.
• Designer de experiência do usuário: um designer de experiência do usuário cria a
experiência do usuário do sistema. Isso inclui o projeto dos elementos de IU (interface
do usuário), o projeto da navegação entre vários formulários, telas ou páginas etc.
O teste de software é usado para assegurar a qualidade do produto final. O teste pode
identificar possíveis lacunas entre as expectativas em relação ao sistema descritas no
documento de requisitos e o comportamento real do sistema.
Entre os participantes mais críticos na atividade de teste de software estão os testadores
que verificam o aplicativo em execução para se certificar de que ele atende aos requisitos
identificados. Quando esses testadores identificam qualquer falha no aplicativo, eles
atribuem cada falha a uma pessoa apropriada que possa consertá-la. Por exemplo, uma
falha de código seria atribuída de volta a um desenvolvedor para que ele (ou ela) possa
remediar o erro.
Os níveis de teste são definidos pela parte em que os testes ocorrem no ciclo de vida
de desenvolvimento do software. Há cinco níveis distintos de teste:
• Teste de unidade: o teste de unidade verifica a funcionalidade de uma unidade de
código. Por exemplo, uma unidade de teste pode avaliar se um método retorna o valor
correto. O teste de unidade é um teste caixa branca e é realizado com frequência pelo
desenvolvedor que está escrevendo o código. O teste de unidade muitas vezes usa
uma ferramenta automatizada que pode simplificar o desenvolvimento dos casos e
também acompanhar se uma modificação do código causa a falha de qualquer um
dos testes de unidade existentes. O Visual Studio tem suporte interno para o teste de
unidade. Você também pode usar ferramentas de software livre, como o NUnit, para
automatizar os testes de unidade para o código do .NET Framework.
• Teste de integração: o teste de integração avalia a interface entre os componentes
de software. O teste de integração pode ser executado de forma incremental enquanto
70 | lição 3
Uma matriz é uma estrutura de dados comum que representa uma coleção de itens de um
tipo semelhante. Os itens de uma matriz são armazenados em locais de memória contígua.
Uma matriz é uma estrutura de dados homogênea, pois todos os itens de uma matriz são
do mesmo tipo de dados. Qualquer item de matriz pode ser diretamente acessado usando
um índice. No .NET Framework, os índices de matriz são de base zero.
REPRESENTAÇÃO INTERNA
No código a seguir, a primeira instrução cria uma variável de matriz, e a segunda
instrução inicializa a variável com uma matriz de quatro números inteiros:
int[] numbers;
numbers = new int[4];
No início, os números variáveis são definidos como null, pois a matriz ainda não foi
inicializada. No entanto, a segunda instrução inicializa a matriz, alocando um espaço
contíguo de memória grande o suficiente para armazenar quatro números inteiros no
heap de memória. O endereço inicial na alocação de memória é armazenado na variável
de matriz numbers, conforme mostra a figura 3-2. Todos os elementos da matriz são
inicializados nesse caso com o valor 0, pois 0 é o valor padrão de um número inteiro.
Figura 3-2
Pilha Heap
Representação interna de
uma estrutura de dados de
int [] numbers; null
matriz
A variável numbers, então, age como uma referência ao local de memória atribuído
à matriz. O nome de matriz pode ser usado para acessar diretamente cada um dos itens
de matriz. No .NET Framework, todas as matrizes são de base zero, ou seja, o primeiro
item da matriz é acessado usando um índice numbers[0], o segundo item é acessado por
numbers[1] e assim por diante.
Também é possível ter matrizes multidimensionais. Uma matriz bidimensional pode
ser comparada a uma tabela na qual cada célula é um elemento de matriz e pode ser
endereçada usando os números de linha e coluna à qual pertence. Tanto o número de linha
quanto o número de coluna são indexados por zero. Por exemplo, a expressão table[2, 3]
se refere a um item na terceira linha e na quarta coluna de uma matriz pelo nome table.
OPERAÇÕES COMUNS
As matrizes dão suporte às seguintes operações:
• Alocação
• Acesso
Para trabalhar com uma matriz, você primeiro deve alocar a memória, criando e
inicializando a matriz, conforme mostrado anteriormente. Após a alocação da matriz,
você poderá acessar qualquer elemento da matriz em qualquer ordem desejada, referindo-
se diretamente ao seu índice. Por exemplo, o código a seguir atribui o valor 10 ao quarto
item da matriz, e o dobro desse valor é atribuído à variável calc:
number[3] = 10;
int calc = number[3] * 2;
72 | lição 3
DESEMPENHO E USO
O conteúdo de uma matriz é disposto como um bloco contíguo de memória e pode ser
acessado diretamente, usando o índice de matriz. Assim, a leitura de uma matriz ou
a gravação nela são procedimentos extremamente rápidos. No entanto, as matrizes são
limitados pelos requisitos de homogeneidade e de tamanho fixo. Embora o tamanho da
matriz possa ser aumentado, isso requer a realocação de todos os elementos da matriz
e é uma operação demorada.
As matrizes funcionam melhor quando o número de itens na coleção é predeterminado
e um acesso rápido e direto a cada item é necessário.
No .NET Framework, você pode usar a classe ArrayList para contornar os requisitos
de homogeneidade e tamanho fixo de uma matriz. Um ArrayList é um tipo de coleção
que pode armazenar itens de qualquer tipo de dados e expandir dinamicamente quando
necessário. No entanto, um ArrayList não é tão rápido quanto uma matriz.
A estrutura de dados da fila imita uma fila da vida real. Em uma fila, os itens são
processados na ordem de sua adição à fila. Em particular, os itens são sempre
adicionados ao final da fila e removidos do início da fila. Isso também é conhecido
como processamento FIFO (primeiro a entrar, primeiro a sair). A capacidade de uma
fila é o número de itens que a fila pode conter. Entretanto, à medida que forem sendo
adicionados elementos à fila, a capacidade aumentará automaticamente. Uma fila
também é uma estrutura de dados heterogêneos, o que significa que os itens de uma fila
podem ser de diferentes tipos de dados.
REPRESENTAÇÃO INTERNA
Para evitar a realocação excessiva do espaço de memória e permitir um gerenciamento
fácil, uma fila muitas vezes é implementada internamente como uma matriz circular de
objetos, conforme mostra a figura 3-3.
Figura 3-3 8 1
Representação interna Head
null null
de uma estrutura de
dados de fila 7 2
null Item 1
Item 5 Item 2
6 3
Item 4 Item 3
Tail
5 4
Dentro de uma fila, o índice de cabeça aponta para o primeiro item, e o índice de cauda
aponta para o último item. Na figura 3-3, por exemplo, o índice de cabeça aponta para
o local 2 na fila. Como a fila é circular, se você conseguir acompanhar os ponteiros de
cabeça e cauda, o início da fila não importará. Quando um item é removido, a cabeça
Noções básicas sobre o desenvolvimento de software em geral | 73
move-se para o próximo item na fila. Quando um novo item é adicionado, ele sempre
TOME NOTA
* aparece no final da fila, e a cauda começa a apontar para o item recém-adicionado.
Uma versão genérica Qualquer slot nulo em uma fila (incluindo o representado na figura 3-3) é o ponto vazio
da classe Queue está que pode ser preenchido antes que a fila necessite de uma realocação de memória.
disponível como parte
O .NET Framework fornece uma implementação da estrutura de dados da fila como parte
do namespace System.
da classe Queue no namespace System.Collections. Nas linguagens de programação que
Collections.Generic.
não fornecem uma implementação de uma fila, você pode escrever sua própria classe Queue
Essa versão genérica
usando uma estrutura de dados semelhante a uma matriz e simulando as operações de fila.
é usada para criar uma
fila de itens que são do
mesmo tipo de dados. OPERAÇÕES COMUNS
Uma fila oferece suporte a estas operações comuns:
• Enfileiramento: a operação de enfileiramento primeiro verifica se há capacidade
disponível suficiente na fila para adicionar mais um item. Se houver capacidade
disponível, o item será adicionado à parte final da fila. Se não houver espaço
disponível na fila, a matriz será realocada por um fator de crescimento
pré-especificado, e o novo item será adicionado à fila.
• Remoção da fila: a operação de remoção da fila remove o elemento atual na frente
da fila e define a cabeça para apontar para o próximo elemento.
• Espiada: a operação espiada permite que você veja o item atual na posição inicial
sem removê-lo realmente da fila.
• Contém: a operação contém permite que você determine se um item específico
existe na fila.
DESEMPENHO E USO
Uma fila é uma estrutura de dados de finalidade especial que é mais adequada a um
aplicativo em que é necessário processar os itens na ordem de seu recebimento. Alguns
exemplos podem incluir spoolers de impressão, sistemas de mensagens e agendadores
de trabalhos. Ao contrário de uma matriz, uma fila não pode ser usada para acessar os
elementos aleatoriamente. As operações, como enfileiramento e remoção da fila,
realmente adicionam e removem itens da fila.
Ao contrário de uma fila, uma pilha é uma estrutura de dados LIFO (último a entrar,
primeiro a sair). Pense em uma pilha como semelhante a uma pilha de pratos de jantar
em uma mesa de bufê; aqui, o último prato a ser adicionado é também o primeiro prato
a ser removido. A capacidade de uma pilha refere-se ao número de itens que ela pode
conter. No entanto, como os elementos são adicionados a uma pilha, a capacidade da
pilha aumenta automaticamente. Uma pilha é uma estrutura de dados heterogêneos,
o que significa que os itens dentro dela podem ser de diferentes tipos de dados.
REPRESENTAÇÃO INTERNA
Assim como uma fila, uma pilha geralmente é implementada como um buffer circular
para evitar realocação excessiva do espaço de memória e permitir um gerenciamento mais
fácil. Uma pilha pode ser visualizada exatamente como a fila mostrada na figura 3-3,
exceto pelo fato de a parte final agora ser chamada de topo da pilha e a parte inicial agora
ser chamada de fundo da pilha.
74 | lição 3
Novos itens são sempre adicionados sobre uma pilha e, quando isso acontece, a parte
TOME NOTA
* superior da pilha começa a apontar para o elemento que acabou de ser adicionado.
Uma versão genérica Os itens também são removidos de cima da pilha e, quando isso acontece, a parte
da classe Stack está superior da pilha é ajustada para apontar para o próximo item da pilha.
disponível como parte
do namespace System. O .NET Framework fornece uma implementação da estrutura de dados da pilha como
Collections.Generic. parte da classe Stack no namespace System.Collections. Nas linguagens de programação
Essa versão genérica que não fornecem uma implementação da pilha, você pode escrever sua própria
é usada para criar uma classe Stack usando uma estrutura de dados semelhante a uma matriz e simulando
pilha de itens que são as operações de pilha.
do mesmo tipo de
dados. OPERAÇÕES COMUNS
Uma pilha oferece suporte a estas operações comuns:
• Push: a operação de envio por push primeiro verifica se há capacidade disponível
suficiente na pilha para adicionar mais um item. Se houver capacidade disponível,
o item será adicionado ao topo da pilha. Se não houver espaço disponível na pilha,
a matriz será realocada por um fator de crescimento pré-especificado, e o novo item
será adicionado à pilha.
• Pop: a operação pop remove o elemento no topo da pilha e define o topo para
apontar para o próximo elemento na pilha.
• Espiada: a operação espiada permite que você veja o item atual na parte superior
da pilha sem removê-lo realmente da pilha.
• Contém: a operação contém permite que você determine se um item específico
existe na pilha.
DESEMPENHO E USO
Uma pilha é uma estrutura de dados de finalidade especial que é mais adequada para as
aplicações em que você precisa processar os itens na ordem último a entrar, primeiro
a sair. As pilhas são estruturas úteis por causa de suas aplicações de gerenciamento de
memória de tempo de execução, avaliação de expressão, acompanhamento de chamada
de método de rastreamento etc. Ao contrário de uma matriz, uma pilha não pode ser
usada para acessar elementos aleatoriamente. As operações, como push e pop, na verdade,
adicionam e removem itens da pilha.
Listas vinculadas
Uma lista vinculada é uma coleção de nós organizados de modo que cada um deles
contenha um link para o próximo nó da sequência.
Uma lista vinculada é uma coleção de nós em que cada nó contém uma referência (ou um
link) para o próximo nó da sequência. Ao contrário de uma matriz, os itens de uma lista
vinculada não precisam ser contíguos; portanto, uma lista vinculada não requer realocação
do espaço de memória para a lista inteira quando for necessário adicionar mais itens.
REPRESENTAÇÃO INTERNA
Na memória, uma lista vinculada pode ser visualizada como uma coleção de nós, como
mostra a figura 3-4.
Figura 3-4
A B C
Representação interna de
uma estrutura de dados de
lista vinculada única Head Null
Noções básicas sobre o desenvolvimento de software em geral | 75
Head Null
Em cada nó de uma lista duplamente vinculada, um link é uma referência direta que
aponta para o próximo nó da sequência, e o outro link é uma referência regressiva que
aponta para o nó anterior na sequência. Como você pode imaginar, uma lista duplamente
vinculada é fácil de ser percorrida em qualquer direção.
O .NET Framework fornece uma classe LinkedList como parte do namespace System.
Collections.Generic. Essa classe implementa uma lista duplamente vinculada homogênea
do tipo de dados especificado. Você também pode escrever suas próprias classes para
implementar um tipo diferente de implementação de lista vinculada.
OPERAÇÕES COMUNS
Uma lista vinculada oferece suporte a estas operações comuns:
• Adicionar: a adição ou a inserção de um item em uma lista vinculada consiste em
alterar links, conforme mostra a figura 3-6. Suponha que você queira inserir um
novo nó (com valor Z) entre os nós com valores A e B. Primeiro, você precisa alocar
Figura 3-6
Z Novo nó
Adicionando um novo nó a
uma lista vinculada
A B C
Head Null
Z Novo nó
A B C
Head Null
76 | lição 3
DESEMPENHO E USO
Uma lista vinculada não permite acesso aleatório aos seus itens. A única maneira de acessar
um item é começar do nó da cabeça e seguir os links a partir dele. Como resultado, as listas
vinculadas demoram a recuperar os dados. No entanto, para as operações de inserção e
exclusão, as listas vinculadas são extremamente rápidas, pois a inserção ou a exclusão de
um nó envolve simplesmente a alteração de um link. As listas vinculadas também não têm
capacidade máxima após a qual seu conteúdo precisará ser realocado.
PRONTO PARA
CERTIFICAÇÃO Na verdade, uma lista vinculada fornece uma maneira alternativa de implementar a fila
Você compreende as e as estruturas de dados de pilha. Se suas necessidades exigirem acesso frequente a dados,
estruturas de dados mas você raramente precisa inserir ou excluir dados, uma matriz será a implementação
comuns? preferida. Se, no entanto, suas necessidades exigirem operações frequentes de inserção
3,2 e exclusão, uma lista vinculada poderá ser uma melhor implementação.
O BubbleSort compara dois elementos para verificar se estão fora de ordem; se estiverem
ele os trocará. O algoritmo continuará fazendo isso até que toda a lista esteja na ordem
desejada. O BubbleSort recebe esse nome pelo modo que o algoritmo funciona: durante
a execução do algoritmo, os itens menores são “flutuados” para cima.
Vamos visualizar BubbleSort com a ajuda de um exemplo. Vamos supor que você queira
organizar todos os itens da lista a seguir em ordem crescente: (20, 30, 10, 40). Esses itens
devem ser organizados do menor para o maior. O algoritmo BubbleSort tenta solucionar
esse problema em um ou mais passos, com cada passo examinando completamente a lista
de itens. Se o algoritmo encontrar elementos fora de ordem, ele os trocará. O algoritmo
termina quando ele examina a lista inteira sem trocar qualquer elemento. Se não houvesse
nenhuma permuta, nenhum dos elementos estariam fora de ordem e a lista teria sido
completamente classificada.
Tabela 3-1
Primeira passagem de Etapa Antes Depois Comentários
BubbleSort
1 20, 30, 10, 40 20, 30, 10, 40 O algoritmo compara os dois primeiros
elementos (20 e 30); como eles estão
na ordem correta, nenhuma permuta
é necessária.
2 20, 30, 10, 40 20, 10, 30, 40 O algoritmo compara os dois
elementos seguintes (30 e 10);
como eles estão fora de ordem,
os elementos são trocados.
3 20, 10, 30, 40 20, 10, 30, 40 O algoritmo compara os dois
elementos seguintes (30 e 40); como
eles estão na ordem correta, nenhuma
permuta é necessária.
Conforme mostra a tabela 3-1, no final da primeira passagem, BubbleSort realizou uma
permuta, e é possível que os itens ainda não estejam totalmente classificados. Portanto,
BubbleSort dá uma outra passagem na lista, conforme ilustrado na tabela 3-2.
Tabela 3-2
Segunda passagem de Etapa Antes Depois Comentários
BubbleSort
1 20, 10, 30, 40 10, 20, 30, 40 algoritmo compara os dois primeiros
O
elementos (20 e 10); como eles estão
fora de ordem, os elementos são
trocados.
2 10, 20, 30, 40 10, 20, 30, 40 algoritmo compara os dois
O
elementos seguintes (20 e 30); como
eles estão na ordem correta, nenhuma
permuta é necessária.
3 10, 20, 30, 40 10, 20, 30, 40 algoritmo compara os dois
O
elementos seguintes (30 e 40); como
eles estão na ordem correta, nenhuma
permuta é necessária.
78 | lição 3
No final da segunda passagem, BubbleSort realizou mais uma permuta, portanto, ele ainda
não pode garantir que a lista esteja completamente classificada. Dessa forma, BubbleSort
realiza uma outra passagem na lista, conforme mostra a tabela 3-3.
Tabela 3-3
Terceira passagem de Etapa Antes Depois Comentários
BubbleSort
1 10, 20, 30, 40 10, 20, 30, 40 algoritmo compara os dois primeiros
O
elementos (10 e 20); como eles estão
TOME NOTA
* na ordem correta, nenhuma permuta é
Quando você usar necessária.
BubbleSort, uma 2 10, 20, 30, 40 10, 20, 30, 40 algoritmo compara os dois
O
matriz será certamente elementos seguintes (20 e 30); como
classificada em uma eles estão na ordem correta, nenhuma
passagem a menos do permuta é necessária.
que o número de itens.
Portanto, se houver 3 10, 20, 30, 40 10, 20, 30, 40 algoritmo compara os dois
O
quatro itens (como no elementos seguintes (30 e 40); como
cenário de exemplo), a eles estão na ordem correta, nenhuma
matriz será classificada permuta é necessária.
(independentemente da
sua ordem de início)
No final da terceira passagem, BubbleSort não realizou nenhuma permuta. Isso garante
em três passagens.
que a lista agora está na ordem de classificação e que o algoritmo pode terminar.
No C#, o algoritmo BubbleSort pode ser expresso pelo seguinte método:
static int[] BubbleSort(int[] numbers)
{
bool swapped;
do
{
swapped = false;
for (int i = 0; i < numbers.Length − 1; i++)
{
if (numbers[i] > numbers[i + 1])
{
//trocar
int temp = numbers[i + 1];
numbers[i + 1] = numbers[i];
numbers[i] = temp;
swapped = true;
}
}
} while (swapped == true);
return numbers;
}
Noções básicas sobre o desenvolvimento de software em geral | 79
O algoritmo QuickSort usa a técnica dividir e conquistar para particionar uma lista
continuamente até que o tamanho do problema seja pequeno e raramente exija
classificação. As etapas a seguir explicam esse processo em mais detalhes:
• Uma lista de tamanho zero ou um sempre é classificada por si só.
• Para obter uma lista maior, escolha qualquer elemento da lista como um elemento
pivô. Em seguida, particione a lista de modo que todos os elementos menores que
ou iguais ao elemento pivô sejam inseridos na lista esquerda e todos os elementos
maiores do que o elemento pivô sejam inseridos na lista direita. Agora, a combinação
da lista esquerda, do elemento pivô e da lista direita estará sempre em ordem
classificada se as listas esquerda e direita estiverem em ordem classificada.
• O problema agora é particionado em duas listas menores, a lista esquerda e a lista
direita.
• Ambas são solucionadas usando a técnica descrita nos marcadores acima.
• Finalmente, todas as pequenas listas classificadas são mescladas para criar a lista
classificada completa final.
A tabela a seguir explica o algoritmo QuickSort com um breve exemplo.
Tabela 3-4
Visualizando o QuickSort Etapa Dados a serem classificados Comentários
1 50, 10, 30, 20, 40 Comece com uma lista não classificada
e escolha um elemento pivô — neste
caso, 30.
2 20, 10 30 50, 40 Particione a lista, inserindo os itens
menores do que o pivô na lista
esquerda e os itens maiores do que o
pivô na lista direita. Em seguida, para
classificar a lista esquerda, escolha um
pivô (neste caso, 10). Da mesma forma,
para classificar a lista direita, escolha
um pivô (neste caso, 40) para essa lista.
3 - 10 20 30 - 40 50 a lista esquerda, 20 é maior do que
N
10 e, na lista direita, 50 é maior do que
40; portanto, tanto 20 quanto 50 serão
inseridos na lista direita. Isso resulta
em listas de apenas um número, que
são todas classificadas por definição.
4 10, 20, 30, 40, 50 Todas as pequenas listas classificadas
são mescladas para criar a lista
classificada final completa.
Até agora, a principal deficiência do algoritmo QuickSort parece ser a memória adicional
necessária à criação de listas menores separadas. No entanto, a criação de listas separadas
não é necessária. Usando uma técnica ligeiramente modificada, a matriz pode ser
particionada no local, como mostra a listagem de código a seguir:
static int Partition (int[] numbers, int left,
int right, int pivotIndex)
80 | lição 3
{
int pivotValue = numbers[pivotIndex];
// mover elemento pivô para o final
int temp = numbers[right];
numbers[right] = numbers[pivotIndex];
numbers[pivotIndex] = temp;
// newPivot armazena o índice do primeiro
// número maior do que o pivô
int newPivot = left;
for (int i = left; i < right; i++)
{
if (numbers[i] <= pivotValue)
{
temp = numbers[newPivot];
numbers[newPivot] = numbers[i];
numbers[i] = temp;
newPivot++;
}
}
//mover o elemento pivô para sua posição classificada
temp = numbers[right];
numbers[right] = numbers[newPivot];
numbers[newPivot] = temp;
return newPivot;
}
Com essa técnica, primeiro o elemento pivô é movido para o final da matriz. Em seguida,
todos os elementos menores que ou iguais ao elemento pivô são movidos para a frente
da matriz. Finalmente, o elemento pivô é colocado antes do elemento maior do que ele
próprio, particionando efetivamente a matriz.
Esse algoritmo de particionamento pode ser usado por QuickSort para particionar a lista,
reduzir o problema em problemas menores e solucioná-lo recursivamente:
static int[] QuickSort(int[] numbers,
int left, int right)
{
if (right > left)
{
int pivotIndex = left + (right − left) / 2;
//partição da matriz
pivotIndex = Partition(
numbers, left, right, pivotIndex);
//classificar a partição esquerda
QuickSort(
numbers, left, pivotIndex − 1);
// classificar a partição direita
QuickSort(
Noções básicas sobre o desenvolvimento de software em geral | 81
RESUMO DE HABILIDADES
■ Avaliação de conhecimento
Preencha as lacunas
Complete as sentenças a seguir com a(s) palavra(s) correta(s) nas lacunas fornecidas.
1. No teste ______, os testadores usam seu conhecimento da estrutura interna do
sistema para avaliar o sistema.
2. Em geral, a cada nova correção, os testadores de software executam uma bateria de
______ para garantir que toda a funcionalidade que antes estava funcionando ainda
esteja em operação.
3. O algoritmo BubbleSort usa uma série de operações de ______ e ______ para
organizar os elementos de uma lista na ordem correta.
82 | lição 3
4. Um(a) ______ é uma coleção de itens em que o último item adicionado à coleção
é o primeiro a ser removido.
5. ______ é o processo que consiste em determinar os requisitos comerciais detalhado
para um novo sistema de software.
6. Uma lista vinculada é uma coleção de nós organizados de modo que cada nó
contenha um(a) ______ para o próximo nó da sequência.
7. A operação de ______ adiciona um item a uma fila, ao passo que a operação de
______ da fila remove um item de uma fila.
8. O algoritmo QuickSort usa operações de ______ e comparação para organizar os
elementos de uma lista na ordem correta.
9. Um(a) ______ é responsável por analisar as necessidades comerciais e convertê-las
em requisitos que possam ser executados pela equipe de desenvolvimento.
10. Os testes alfa e beta fazem parte do teste de ______ de um sistema.
Múltipla escolha
Assinale a letra que corresponde à melhor resposta.
1. O produto que você está desenvolvendo ainda não está concluído, mas você deseja
lançá-lo para um público-alvo maior do cliente para testá-lo e obter feedback.
Em qual dos níveis de teste a seguir essa atividade se enquadraria?
a. Teste de integração
b. Teste de sistema
c. Teste de aceitação
d. Teste de regressão
2. Os testadores de um software têm acesso ao seu código-fonte e planejam escrever
casos de teste que garantam que os métodos retornem valores corretos. Em qual
dos níveis de teste a seguir essa atividade se enquadraria?
a. Teste de integração
b. Teste de unidade
c. Teste alfa
d. Teste beta
3. Qual das estruturas de dados a seguir permite acesso direto a todos os seus itens?
a. Matriz
b. Pilha
c. Fila
d. Lista vinculada
4. Qual das atividades a seguir do ciclo de vida do aplicativo é usada por um arquiteto
para criar o plano gráfico técnico de um sistema?
a. Análise de requisitos
b. Design
c. Desenvolvimento
d. Manutenção
5. No seu aplicativo, você está usando uma estrutura de dados de fila para manipular as
informações. Você precisa descobrir qual item de dados será processado em seguida,
mas não deseja realmente processá-lo. Qual das operações de fila a seguir você usará?
a. Enfileiramento
b. Remoção da fila
c. Espiada
d. Contém
Introdução à programação orientada a objeto | 83
■ Avaliação da competência
Cenário 3-1: Usando matrizes
Você está escrevendo um programa que usa uma matriz bidimensional. A matriz tem
quatro linhas e cinco colunas. Você precisa imprimir o maior elemento de cada linha da
matriz. Como você escreveria esse programa?
84 | lição 3
■ Avaliação de proficiência
Cenário 3-3: Usando pilhas
Você está escrevendo um programa que usa duas pilhas. Os dados de cada pilha já estão
em ordem decrescente. Você precisa processar o conteúdo das duas pilhas de modo que
a saída seja impressa na tela em ordem crescente. Como você escreveria esse programa?
P R I N C I PA I S T E R M O S
folhas de estilos em cascata (CSS) JavaScript diretório virtual
programação do lado do cliente SOAP (Simple Object Access Hospedagem Web
gerenciamento de estado do lado Protocol) Serviços Web
do cliente programação do lado do servidor WSDL (Web Service Description
HTML (Hypertext Markup Language) gerenciamento de estado do lado Language)
IIS (Serviços de Informações da Internet) do servidor site
gerenciamento de estado
A linguagem HTML (Hypertext Markup Language) é a usada pelo servidor Web e pelo
navegador da Web para descrever uma página da Web. HTML é uma linguagem baseada
em texto que usa diversas marcas que descrevem como o conteúdo é exibido. O HTML
permite que imagens, vídeos e outros objetos sejam referenciados em um arquivo para
criar páginas da Web multimídia. O HTML também pode inserir scripts (como JavaScript)
que afetam o comportamento das páginas da Web e pode ser usado para incluir folhas de
estilos em cascata (CSS) para definir a formatação e o layout do conteúdo de uma página.
O navegador da Web lê o código HTML e renderiza os resultados na tela.
Uma página da Web pode conter hiperlinks para outros recursos, como imagens e vídeos.
Cada um desses recursos é identificado por sua própria URL. Assim, para renderizar uma
página completamente, o navegador fará solicitações HTTP adicionais para obter esses
recursos e exibi-los como parte da página da Web.
Nas seções a seguir, você aprenderá mais sobre os vários componentes que compõem uma
página da Web, incluindo HTML, CSS e JavaScript.
Esta lição não abrange todos os elementos HTML. Para saber mais sobre esses
TOME NOTA
* elementos, procure por "Elementos HTML" no MSDN.
<body>
<h1>Mimas Cassini</h1>
A marca img é usada para exibir a imagem de uma
<a href="http://en.wikipedia.org/wiki/Mimas_(moon)">
lua de Saturno</a>: <br />
<img height="400px" width="400px"
alt="Mimas Cassini"
src="http://goo.gl/3BeK"/>
</body>
</html>
4. Selecione Depurar > Iniciar Depuração (ou pressione F5). A página default.htm será
aberta em um navegador da Web. A saída deve ser semelhante à figura 4-1, onde você
poderá ver as marcas <img> e <a> em ação.
Figura 4-1
Uma página HTML simples
contendo uma imagem e um
hiperlink
facilidade de manutenção de um site. Por exemplo, suponha que você queira alterar a cor
e a fonte de todos os títulos H1 em seu site. Uma abordagem pode ser abrir um editor de
HTML e modificar cada arquivo no site que usa a marca H1. Isso poderá ser uma solução
aceitável se o site tiver apenas uma ou duas páginas, mas e se o site tiver um grande
número de páginas, por exemplo, 50 ou 100? Imagine alterar manualmente cada página!
TOME NOTA
* Se essas alterações forem solicitadas com frequência, o processo de desenvolvimento da
Quando usado Web será entediante e propenso a erro. Afinal, como você pode garantir que não perdeu
efetivamente, nenhuma marca H1?
CSS é uma ótima Felizmente, com o CSS, você poderá incluir todas as informações de estilo em um arquivo
ferramenta para separado e conectar esse arquivo a todas as páginas em um site. Em seguida, assim que
aumentar a consistência o arquivo CSS estiver configurado, você poderá modificar qualquer estilo (por exemplo,
e a facilidade de a cor e a fonte dos títulos H1) simplesmente alterando o estilo no arquivo CSS — e essa
manutenção de todo única alteração afetará todas as páginas no site.
o site.
PROJETANDO FOLHAS DE ESTILOS EM CASCATA
A linguagem CSS é baseada em texto e fácil de ler e compreender. O exemplo a seguir
é de uma página HTML que define estilos CSS:
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title>Noções básicas sobre CSS</title>
<style type="text/css">
body
{
font-family: Verdana;
font-size: 9pt;
}
div
{
color:Red;
}
.block
{
background-color: Yellow;
border-color: Blue;
border-width: thin;
border-style: outset;
font-family: Arial;
}
</style>
</head>
<body>
Texto de corpo de exemplo <br />
<div>Texto de DIV de exemplo</div>
<div class="block">Texto de DIV de exemplo
com classe block</div>
<span class="block">Texto de SPAN de exemplo
com classe block</span>
</body>
</html>
90 | lição 4
Observe que as definições CSS devem estar dentro do elemento <style> e são definidas
sob o elemento <head>. Esse CSS específico define dois estilos de elemento e um estilo de
classe. O primeiro estilo aplica-se ao elemento body HTML e especifica que todo o texto
no elemento body deve usar a fonte Verdana e 9 pontos de tamanho. O segundo estilo de
elemento especifica que o texto dentro do elemento DIV deve ser escrito em vermelho.
Finalmente, uma classe denominada “block” é definida. As definições de classe CSS são
prefixadas com um ponto (“.”). O conteúdo de qualquer elemento HTML que usa essa
classe será exibido com plano de fundo amarelo e uma borda. Quando você exibir essa
página específica em um navegador, ela deverá aparecer conforme mostra a figura 4-2.
Figura 4-2
Formatando HTML com
folhas de estilos em cascata
Na figura, observe que o texto realçado é exibido como resultado da classe block. No
entanto, a classe CSS block não especifica a cor do texto. Na primeira linha do texto
realçado, a classe block é aplicada ao elemento DIV; na segunda linha do texto realçado,
a classe block é aplicada ao elemento SPAN. No primeiro caso, como a classe block é
aplicada a um texto DIV, o estilo de cor do elemento DIV é transportado na renderização
final.
No exemplo anterior, o arquivo CSS foi escrito dentro do arquivo HTML. Uma
abordagem mais útil consiste em escrever o CSS em seu próprio arquivo separado e, em
seguida, vincular o arquivo HTML a esse arquivo CSS. Você aprenderá como fazer isso
no próximo exercício.
.block
{
background-color: Yellow;
border-color: Blue;
border-width: thin;
border-style: outset;
font-family: Arial;
}
3. Selecione Projeto > Adicionar Novo Item e, em seguida, selecione o modelo Página
HTML. Nomeie o arquivo como default.htm. Substitua o código padrão no arquivo por
este:
<!DOCTYPE html PUBLIC
"–//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1–
transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<link rel="STYLESHEET"
type="text/css" href="styles.css" />
<title>Noções básicas sobre CSS</title>
</head>
<body>
Texto do corpo de exemplo <br />
<div>Texto de DIV de exemplo</div>
<div class="block">Texto de DIV de exemplo
com classe bloco</div>
<span class="block">Texto de SPAN de exemplo
com classe bloco</span>
</body>
</html>
TOME NOTA
* 4. Selecione Depurar > Iniciar Depuração (ou pressione F5). A página default.htm
Quando CSS forem será aberta em um navegador da Web, e a saída deverá ser semelhante à figura 4-2
armazenadas em (apresentada anteriormente).
arquivos separados, o
navegador do usuário Conforme mostrado no exercício de exemplo, o elemento HTML <link> é usado para
baixará e armazenará vincular um arquivo CSS a uma página HTML:
esses arquivos <link rel="STYLESHEET"
localmente. Portanto, type="text/css" href="styles.css" />
elas poderão ser usadas
em várias páginas, sem O elemento <link> é sempre colocado dentro do elemento <head>, e o atributo href
qualquer necessidade especifica o endereço do arquivo CSS a ser usado. Para vincular várias páginas ao mesmo
de serem baixadas arquivo CSS, você precisará colocar o elemento <link> dentro de cada página HTML.
novamente. Isso reduz O Visual Studio inclui um designer de estilo interno que pode ajudar você a projetar
a transferência de novos estilos CSS ou modificar os estilos existentes. Ao abrir um arquivo .css, você
dados desnecessária. verá um novo menu denominado Estilos. Nesse menu, você pode criar um novo estilo,
selecionando Estilos > Adicionar Regra de Estilo. Você também pode modificar o estilo
escolhido no momento, selecionando a opção Estilos > Criar Estilo. Essa opção abre caixa
de diálogo Modificar Estilo, como mostra a figura 4-3.
92 | lição 4
Figura 4-3
Caixa de diálogo Modificar
Estilo
O JavaScript é usado para tornar os sites mais dinâmicos e as páginas da Web mais
interativas. Com o JavaScript, isso é feito executando o código no lado do cliente (o
navegador da Web) e minimizando as viagens de ida e volta desnecessárias entre o
servidor Web. Vamos usar um exemplo em que um usuário precisa inserir detalhes
pessoais em uma página da Web, como nome, endereço de email e número de telefone.
Um requisito comum consiste em executar a validação dos dados para garantir que os
campos de entrada não estejam vazios e o endereço de email e o número de telefone
do usuário tenham sido fornecidos no formulário obrigatório. Sem o JavaScript, você
precisaria enviar o formulário para o servidor, que executaria a validação do dados
e retornaria os resultados ao cliente. Essa transmissão de informações leva tempo e
prejudica a experiência do usuário. No entanto, uma solução JavaScript pode executar
esse tipo de validação de dados a partir do navegador, proporcionando uma melhor
experiência do usuário.
Como mencionado anteriormente, o código JavaScript é executado localmente dentro
do navegador da Web (o cliente), e não no servidor Web. Portanto, o JavaScript às vezes
também é chamado de linguagem de scripts do lado do cliente, e a programação com
JavaScript é chamada de programação do lado do cliente.
O comportamento em tempo de execução da execução do código do lado do cliente
dependerá do navegador que o executar. No entanto, esse comportamento é independente
da tecnologia de servidor ou da estrutura de programação. Portanto, para o JavaScript
que está sendo executado em um navegador da Web, não importa se a página da Web foi
gerada por ASP.NET ou PHP ou se a página está sendo disponibilizada por um servidor
Web do Windows ou do Linux.
Tanto o JavaScript quanto a linguagem de programação C# usam uma sintaxe influenciada
pela linguagem de programação C. Apesar disso, JavaScript e C# são muito diferentes em
seu modo de execução. Em particular, o JavaScript é executado pelo navegador da Web, e
o código JavaScript é interpretado, em vez de ser compilado, como no caso de C#.
Noções básicas sobre aplicativos Web | 93
Vários sites modernos fornecem uma experiência altamente interativa, rivalizando com
a de aplicativos desktop. Esses sites podem ser desenvolvidos usando a programação
Ajax. Ajax é uma abreviação de "Asynchronous JavaScript and XML". Ajax usa
*
TOME NOTA
JavaScript extensivamente para fornecer aplicativos Web dinâmicos. A estrutura do
AJAX ASP.NET permite que você implemente a funcionalidade Ajax nas páginas da
Web ASP.NET.
Todo o código JavaScript deve ser colocado dentro do elemento <script>. O elemento
<script> geralmente é colocado dentro do elemento <head>, embora isso não seja
necessário. Vários elementos <script> podem existir dentro de uma única página. Para ver
o JavaScript em ação, execute o exercício a seguir.
3. Selecione Depurar > Iniciar Depuração (ou pressione F5). A página default.htm será
aberta em um navegador da Web. Observe que o código JavaScript solicita que você
insira seu nome. Em seguida, uma caixa de diálogo exibe uma mensagem com base no
comprimento do seu nome, como mostram as figuras 4-4 e 4-5.
Figura 4-4
Prompt de usuário de
JavaScript
Figura 4-5
Caixa de diálogo JavaScript
Assim como acontece com os arquivos CSS, você também pode colocar seu código
JavaScript em um arquivo separado e vincular esse arquivo a um arquivo HTML, usando
o elemento script, conforme mostrado abaixo:
<script src="SampleScript.js">
</script>
Aqui, o arquivo SampleScript.js contém todo o código JavaScript, e o elemento script
TOME NOTA
* é vinculado a esse arquivo, usando o atributo src. O armazenamento do JavaScript em
Embora todos os arquivos externos oferece várias vantagens:
navegadores modernos
ofereçam suporte a • Maior facilidade de manutenção: se usar o mesmo código JavaScript em cada
JavaScript, eles podem página de um site, você poderá armazenar o código em uma página central, em vez
ser definidos para de repeti-lo em cada página. Dessa forma, quando for o momento de modificar o
que JavaScript seja código JavaScript, você precisará alterá-lo em um único lugar.
desligado. Você pode • Melhor desempenho: o armazenamento do código JavaScript em um arquivo
usar um elemento separado reduz o tamanho de uma página da Web. Além disso, os navegadores
<noscript> para podem baixar e armazenar em cache o arquivo JavaScript externo para que ele não
exibir uma mensagem seja baixado novamente, a menos que seja modificado.
específica aos usuários
O Visual Studio inclui suporte total do IntelliSense para o código JavaScript. Até mesmo
que optarem por não
os controles ASP.NET, como o controle TreeView ou os controles de validação, usam
executar o JavaScript.
JavaScript sempre que possível para renderizar um conteúdo dinamicamente.
Noções básicas sobre programação do lado do cliente versus lado do servidor
Um programa do lado do cliente ou do lado do servidor depende de onde ele é
executado no final.
Figura 4-6
Comunicação entre um
cliente e um servidor Web
96 | lição 4
Como desenvolvedor, você deve saber de forma oculta quando um servidor Web executa
uma solicitação de uma página ASP.NET. As etapas a seguir descrevem esse processo:
1. Quando o IIS (Serviços de Informações da Internet) recebe uma solicitação HTTP,
ele usa a extensão de nome de arquivo para determinar qual programa ISAPI
(Internet Server Application Programming Interface) deve ser executado para
processar a solicitação. Quando a solicitação for para uma página ASP.NET, ele
passará a solicitação para a DLL ISAPI capaz de lidar com solicitações de páginas
ASP.NET, a aspnet_isapi.dll.
2. O processo aspnet_isapi.dll passa a solicitação para o processo de trabalho ASP.NET
(aspnet_wp.exe), que atende à solicitação.
3. O processo de trabalho ASP.NET compila o arquivo .aspx em um assembly e instrui
o CLR (Common Language Runtime) para executar o assembly.
4. Quando o assembly é executado, ele utiliza os serviços de várias classes na biblioteca
de classes .NET Framework para realizar o seu trabalho e gerar mensagens de
resposta para o cliente solicitante.
5. O processo de trabalho ASP.NET coleta as respostas geradas pela execução da página
da Web, cria um pacote de resposta e passa-o para o processo aspnet_isapi.dll.
6. O aspnet_isapi.dll, encaminha o pacote de resposta para o IIS, que, por sua vez, passa
a resposta para a máquina cliente solicitante.
Antes da execução, cada página ASP.NET é convertida em uma classe. Essa classe deriva
a maior parte de sua funcionalidade da classe System.Web.UI.Page. A classe Page fornece
várias propriedades importantes, como Request, Response, Session e Server.
A classe Page fornece vários métodos e propriedades importantes que controlam como
*
TOME NOTA uma solicitação de página é processada. Para obter uma lista completa de métodos
e propriedades, visite http://msdn.microsoft.com/en-us/library/system.web.ui.page.aspx.
Durante sua execução, uma página ASP.NET passa por vários estágios distintos
de processamento. Cada um desses estágios passa por etapas de processamento
específicas, como inicialização, carregamento, execução do código de manipulador
de eventos e renderização.
Quando uma página é executada, ela passa por vários estágios de processamento. A
página também dispara alguns eventos aos quais você pode anexar um manipulador de
eventos para executar um código personalizado em diferentes estágios de processamento
da página. Na verdade, os desenvolvedores ASP.NET devem ter uma boa compreensão do
ciclo de vida da página, para poderem escrever o código executado exatamente no estágio
desejado de processamento da página.
A tabela 4.1 lista os diferentes estágios do ciclo de vida e seus eventos associados.
Tabela 4-1
Estágios importantes no ciclo de vida da página ASP.NET
Quando quiser manipular um evento, você deve escrever um código que registre um método para
manipular o evento (também chamado de manipulador de eventos) com o evento. Isso geralmente
é feito usando o padrão de registro de evento comum empregado em todo o .NET Framework:
object.event += new EventHandler(eventhandler);
Aqui, substitua object pelo nome do objeto que expõe o evento, event pelo nome do evento
e eventhandler pelo nome do método que manipula o evento.
No entanto, observe que o ASP.NET fornece, por padrão, seis métodos especiais que são
reconhecidos como manipuladores de eventos e não precisam do código de registro acima.
Eles são os métodos especialmente nomeados Page_Load, Page_Init, Page_DataBind,
Page_PreRender e Page_Unload. Esses métodos são tratados como manipuladores de
eventos para os eventos correspondentes expostos pela classe Page. Essa ligação automática
de eventos é controlada pelo atributo AutoEventWireup da diretiva @Page. Por padrão,
o valor desse atributo é true, o que significa que esses métodos especialmente nomeados são
automaticamente conectados aos seus eventos correspondentes.
98 | lição 4
PREPARE-SE. Para ver como diferentes eventos de classe Page são executados, realize
estas ações:
1. Crie um novo projeto com base no modelo Aplicativo Web Vazio do ASP.NET para a
solução Lesson04. Nomeie o projeto como PageEvents.
2. Selecione Projeto > Adicionar Novo Item. Selecione o modelo Formulário da Web.
Nomeie o arquivo como WebForm1.aspx.
3. Na marcação HTML da página (WebForm1.aspx), verifique se o atributo
AutoEventWireup para a diretiva @Page é definido como true:
<%@ Page Language="C#" AutoEventWireup="true"
CodeBehind="WebForm1.aspx.cs"
Inherits="PageEvents.WebForm1" %>
4. Clique com o botão direito do mouse na janela de código e selecione Exibir Código no
menu de atalho para alternar para o modo de exibição de código. Substitua o código
no arquivo code-behind (WebForm1) por este:
using System;
namespace PageEvents
{
public partial class WebForm1
: System.Web.UI.Page
{
protected void Page_Load
(object sender, EventArgs e)
{
Response.Write
("Message from Page_Load. <br/>");
}
protected void Page_Init
(object sender, EventArgs e)
{
Response.Write
("Mensagem de Page_Init. <br/>");
}
protected void Page_PreRender
(object sender, EventArgs e)
{
Response.Write
("Mensagem de Page_PreRender. <br/>");
}
protected void Page_PreInit
(object sender, EventArgs e)
{
Response.Write
("Mensagem de Page_PreInit. <br/>");
}
}
}
Noções básicas sobre aplicativos Web | 99
5. Selecione Depurar > Iniciar Depuração (ou pressione F5). A página default.htm será
aberta em um navegador da Web, como mostra a figura 4-7.
Figura 4-7
Formulário da Web exibindo
a ordem de execução de
eventos para uma página
ASP.NET
No exercício de exemplo, observe que os caracteres <% e %> são usados para inserir
blocos de código na marcação HTML de uma página. O código dentro desses blocos
inseridos é executado durante o estágio de renderização da página. Dentro dos blocos
de código inseridos, a sintaxe <%=expression> é usada para resolver uma expressão
e retornar seu valor ao bloco. Por exemplo, considere o seguinte bloco de código:
<i><% = DateTime.Now.ToShortDateString() %></i>
Quando executado, esse código exibirá a data atual em itálico:
12/01/2010
A diretiva @Page especifica vários atributos que controlam como o ASP.NET renderizará
uma página. Por exemplo, neste exercício, os atributos da diretiva @Page especificam
o seguinte:
• C# é a linguagem de programação desta página da Web (Language="C#")
• Os eventos da página são automaticamente ligados (AutoEventWireup=true)
• O nome do arquivo de código que contém a classe associada à página
(CodeBehind="WebForm1.aspx.cs")
• O nome de classe para a página a ser herdada (Inherits="PageEvents.WebForm1")
O gerenciamento de estado é o processo que mantém o estado de uma página da Web nas
viagens de ida e volta. Os valores das variáveis e dos controles compõem coletivamente o
estado de uma página da Web.
O ASP.NET fornece várias técnicas para preservar as informações de estado nos postbacks
de página. Essas técnicas podem ser amplamente classificadas como do lado do cliente ou
do lado do servidor, dependendo de onde os recursos são consumidos.
100 | lição 4
<body>
<form id="form1" runat="server">
<div>
<asp:Label ID="Label1" runat="server"
Text="Insira seu nome:" /><br />
<asp:TextBox ID="TextBox1" runat="server" />
<br /><br />
<asp:Button ID="Button1" runat="server"
Text="Submit" onclick="Button1_Click" />
</div>
</form>
</body>
</html>
4. Clique com o botão direito do mouse na janela de código e selecione Exibir Código
no menu de atalho para alternar para o arquivo code-behind (WebForm1.aspx.cs).
Substitua o código desse arquivo pelo seguinte:
using System;
namespace UsingSessionState
{
public partial class WebForm1
: System.Web.UI.Page
{
protected void Page_Load
(object sender, EventArgs e)
{
if (Session["Name"] != null)
Response.Redirect("WebForm2.aspx");
}
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Label ID="Label1" runat="server" /> <br />
<asp:Button ID="Button1" runat="server"
Text="Limpar sessão"
onclick="Button1_Click" />
</div>
</form>
</body>
</html>
6. Altere o código no arquivo code-behind (WebForm2.aspx.cs) para o formulário, para
que ele seja lido como:
using System;
namespace UsingSessionState
{
public partial class WebForm2
: System.Web.UI.Page
{
protected void Page_Load(
object sender, EventArgs e)
{
if (Session["Nome"] != null)
Label1.Text = String.Format(
"Bem-vindo, {0}", Session["Nome"]);
else
Response.Redirect("WebForm1.aspx");
}
protected void Button1_Click(
object sender, EventArgs e)
{
Session.Remove("Nome");
Response.Redirect("WebForm1.aspx");
}
}
}
7. Selecione Depurar > Iniciar Depuração (ou pressione F5). A página WebForm1.aspx
será aberta em um navegador da Web, conforme mostra a figura 4-8. Digite um nome
e clique no botão Enviar. Esta página armazena o nome digitado no estado de sessão.
104 | lição 4
Figura 4-8
Esta página armazena o
nome digitado no estado de
sessão
PRONTO PARA
CERTIFICAÇÃO
Você compreende 8. Em seguida, você será transferido para WebForm2.aspx, conforme mostra a figura 4-9.
as noções básicas de WebForm2.aspx recupera o nome de usuário do estado de sessão. Na mesma janela
desenvolvimento de do navegador (de modo que você esteja dentro da mesma sessão), tente acessar
aplicativos Web ASP. WebForm1.aspx. Observe que, enquanto a sessão contiver uma entrada para o nome,
NET? você será redirecionado para WebForm2.aspx. Pressione o botão Limpar Sessão. Isso
4.2 limpará a sessão e o transferirá para WebForm1.aspx.
Figura 4-9
Esta página recupera o nome
exibido do estado de sessão
Você pode usar o IIS para hospedar vários sites e compartilhar informações com
usuários pela Internet ou por uma intranet. O IIS usa uma relação hierárquica entre sites,
aplicativos e diretórios virtuais como um bloco de construção básico para a hospedagem
de conteúdo online.
O IIS pode ser administrado usando a ferramenta Gerenciador do IIS, que faz parte
do sistema operacional Windows. A ferramenta Gerenciador do IIS, como mostra a
figura 4-10, fornece uma interface gráfica do usuário para configurar sites, aplicativos e
diretórios virtuais. A captura de tela na figura 4-10 é de um computador que executa o
Windows 7. A interface do usuário do Gerenciador do IIS é diferente no Windows XP.
Figura 4-10
Interface do Gerenciador
de Serviços de Informações
da Internet (IIS) em um
computador que executa
o Windows 7
físicos. Esses aliases também são chamados de diretórios virtuais. Os diretórios virtuais
tornam-se parte da URL, como demonstrado no exemplo anterior. Quando o IIS recebe
uma solicitação para uma URL desse tipo, ele mapeia o diretório virtual para o local físico
dos arquivos. O exercício a seguir mostra como criar um diretório virtual.
Um serviço Web é um componente de software que pode ser acessado em uma rede
O RESULTADO
usando protocolos de rede padrão, por exemplo, HTTP. Os serviços Web são descritos
usando WSDL (Web Services Description Language).
Introdução ao SOAP
O SOAP é o protocolo para a troca de informações estruturadas em uma
comunicação de serviço Web entre dois computadores remotos.
SOAP é o protocolo que define como computadores remotos trocam mensagens como
parte de uma comunicação de serviço Web. SOAP depende de XML como seu formato
de mensagem e usa HTTP para transmissão de mensagens. O uso do SOAP para a
comunicação traz dois benefícios importantes. Primeiro, como as mensagens de serviços
Web são formatadas como XML, elas são mais fáceis de serem compreendidas por
sistemas incompatíveis. Em segundo lugar, como essas mensagens são transmitidas pelo
HTTP penetrante, elas normalmente podem atingir qualquer máquina na Internet sem
serem bloqueadas por firewalls.
Este é um pacote SOAP típico enviado de um cliente para um serviço Web:
<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope
xmlns:xsi=http://www.w3.org/2001/XMLSchema–instance
xmlns:xsd=http://www.w3.org/2001/XMLSchema
xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/">
<soap:Body>
<ToLower xmlns="http://northwindtraders.com">
<inputString>SEQUÊNCIA DE AMOSTRA</inputString>
</ToLower>
</soap:Body>
</soap:Envelope>
108 | lição 4
Introdução ao WSDL
WSDL é uma linguagem baseada em XML para descrever serviços Web.
*
TOME NOTA WSDL significa Web Services Description Language e fornece um padrão pelo qual um
Um serviço Web pode serviço Web pode informar ao seu cliente qual tipo de mensagens ele aceitará e quais
existir sem um arquivo resultados serão retornados. Um arquivo WSDL funciona como a interface pública de um
WSDL, mas você deve serviço Web e inclui as seguintes informações:
conhecer a mensagem • Os tipos de dados que ele pode processar
SOAP exata de entrada
• Os métodos que ele expõe
esperada pelo serviço
Web antes de usar esse • As URLs através das quais esses métodos podem ser acessados
serviço.
Criando serviços Web
Nesta seção, você aprenderá a criar e publicar um serviço Web.
Nesta seção, você aprenderá a criar um serviço Web simples denominado TextWebService
que expõe dois métodos, ToLower e ToUpper. Esses métodos converter uma determinada
cadeia de caracteres em letras minúsculas e maiúsculas, respectivamente. Embora este
exemplo seja simples, ele abrange todos os aspectos de criação de um serviço Web que
pode envolver uma lógica de processamento mais complexa.
Noções básicas sobre aplicativos Web | 109
2. Selecione Projeto > Adicionar Novo Item no menu de atalho. Selecione o modelo
Serviço Web, conforme mostra a figura 4-13. Nomeie o serviço Web como
TextWebService.asmx.
Figura 4-13
Selecione o modelo Serviço
Web
{
[WebMethod]
public string ToUpper(string inputString)
{
return inputString.ToUpper();
}
[WebMethod]
public string ToLower(string inputString)
{
return inputString.ToLower();
}
}
4. Selecione Depurar > Compilar TextWebService para compilar o projeto e garantir que
TOME NOTA
* não há erros. O serviço Web agora está pronto para uso.
Você pode usar o nome No código acima, há alguns itens importantes a serem observados. Primeiro, observe que
de domínio da sua cada classe exposta como um serviço Web XML precisa ter um atributo WebService. O
empresa como parte atributo WebService tem uma propriedade Namespace que assume como padrão https://
do namespace para tempuri.org/. Embora não haja problemas ter esse valor no momento do desenvolvimento,
distinguir seus serviços o valor do namespace deverá ser alterado antes que o serviço Web seja publicado. Na
Web dos serviços verdade, cada serviço Web individual deve ter um namespace exclusivo para que os
publicados por outras aplicativos cliente o diferencie dos outros serviços Web.
empresas.
Cada método exposto do serviço Web também precisa ter um atributo WebMethod. Os
métodos marcados com atributos WebMethod também são conhecidos como métodos
Web. Os dois métodos utilizados neste exercício convertem uma determinada cadeia de
caracteres em letras maiúsculas e minúsculas, respectivamente.
Para testar um serviço Web simples, como o TextWebService criado acima, você precisa
apenas de um navegador da Web. Você poderá selecionar os métodos a serem invocados,
passar parâmetros e examinar os valores de retorno dentro do navegador, conforme
mostrado no exercício a seguir.
TESTAR UM SERVIÇO WEB
2. Na página de teste, clique no link Descrição do Serviço. Dessa forma, você será capaz
de exibir a linguagem WSDL para esse serviço Web. Clique no botão Voltar para
retornar à página de teste.
3. Observe que todos os métodos Web aparecem como links na página de teste. Para
invocar um método Web específico, clique no respectivo link. Depois isso, você verá
uma página para testar o método Web selecionado, como mostra a figura 4-15.
Figura 4-15
Página de teste de
método Web
Figura 4-17
Caixa de diálogo Adicionar
Referência da Web
Figura 4-18
Nó Web References para
o projeto
Método ToUpper:
<asp:Label ID="toUpperLabel"
runat="server"
Text="Label" ForeColor="Green" />
</p>
</form>
</body>
</html>
5. Abra o modo de exibição de Design para default. aspx e clique duas vezes no controle
Button. Isso adicionará o código para o manipulador de eventos Click. Modifique o
TOME NOTA
* código como mostrado abaixo:
Ao invocar um método protected void Button1_Click(
de serviço Web, você object sender, EventArgs e)
pode optar por usar
um método síncrono {
ou assíncrono. Você var webService =
pode querer usar o new textWebService.TextWebService();
método assíncrono para toLowerLabel.Text =
aumentar a capacidade
de resposta do webService.ToLower(TextBox1.Text);
aplicativo cliente. toUpperLabel.Text =
webService.ToUpper(TextBox1.Text);
}
6. Selecione Depurar > Iniciar Depuração para executar o aplicativo Web. Digite um texto
de exemplo e, em seguida, clique no botão Invocar Métodos de Serviço. Você verá os
resultados em TextWebService, como mostra a figura 4-19.
Figura 4-19
Valor de retorno do serviço
Web
No exercício acima, quando você adicionar uma referência da Web, o Visual Studio criará
um proxy local que representa o serviço remoto. O proxy simplifica a comunicação com o
serviço Web, aceitando mensagens, encaminhando-as para o serviço Web e retornando os
resultados do serviço Web.
Você pode usar esse proxy facilmente para criar objetos do serviço Web e invocar
métodos. Como resultado, o trabalho com objetos remotos é semelhante ao trabalho com
objetos locais.
Noções básicas sobre aplicativos Web | 115
Quando você cria uma referência da Web, o Visual Studio lê o arquivo WSDL apropriado
PRONTO PARA
CERTIFICAÇÃO para determinar quais classes e métodos estão disponíveis no servidor remoto. Quando
Você compreende você chama um método em um objeto remoto, o .NET Framework converte sua chamada
as noções básicas de em mensagens SOAP e transmite-as sem qualquer intervenção da sua parte.
desenvolvimento de
serviços Web?
4.4
RESUMO DE HABILIDADES
■ Avaliação de conhecimento
Preencha as lacunas
Complete as frases a seguir com a(s) palavra(s) correta(s) nas lacunas fornecidas.
1. Na marca de ancoragem HTML (<a>), o atributo _________ especifica a URL
de destino.
2. Você pode colocar o código CSS em um arquivo separado e vinculá-lo a uma página
da Web por meio do uso do elemento HTML _________.
3. O código JavaScript em uma página da Web é executado no _________.
116 | lição 4
4. Você pode usar um elemento _________ para exibir uma mensagem específica para
os usuários quando seu navegador não está executando JavaScript.
5. Você pode desabilitar ViewState no nível de página, definindo o atributo _________
da diretiva Page para false na página ASP.NET.
6. O estado _________ é usado para armazenar dados que são usados globalmente por
meio de um aplicativo, em oposição ao estado _________, que armazena dados para
uma sessão de usuário.
7. Um aplicativo Web é acessado usando um nome _________ em vez de um nome de
pasta física.
8. Você deve marcar as classes com o atributo _________ para expô-las como um
serviço Web.
9. De todos os métodos em uma classe de serviço Web, somente as marcadas com os
atributos _________ são expostas como métodos de serviço Web.
10. SOAP depende de _________ como seu formato de mensagem e usa _________ para
a transmissão de mensagens.
Múltipla escolha
Assinale a letra que corresponde à melhor resposta.
1. Escreva o código a seguir para a sua página da Web:
<html>
<head>
<title>Página de exemplo</title>
<style type="text/css">
div
{
font-family: Verdana;
font-size: 9pt;
}
</style>
</head>
<body>
<div style=
"font-weight: bold; font-size: 12pt;">
Página de texto</div>
</body>
</html>
Qual seria o estilo do texto exibido como parte do elemento <div>?
a. Font family: Verdana; font weight: bold; font size: 12pt
b. Font family: Verdana; font weight: bold; font size: 9pt
c. Font family: Verdana; font size: 12pt
d. Font family: Verdana; font size: 9pt
Noções básicas sobre aplicativos Web | 117
8. Seu aplicativo cliente chama um serviço Web que realiza cálculos complexos
e demorados. Um usuário reclama que, enquanto os resultados estão sendo
retornados, a interface de usuário congela momentaneamente. Qual abordagem você
deve tomar para resolver este problema?
a. Você deve instalar um processador melhor no servidor Web.
b. Você deve instalar um processador melhor no computador cliente.
c. Você deve atualizar para uma conexão de Internet mais rápida.
d. Você deve usar chamadas assíncronas para chamar o serviço Web.
9. Você criou um serviço Web ASP.NET que converte uma moeda em outra. Um dos
métodos no seu serviço Web é definido com o código a seguir:
public double Convert(double amount,
string from, string to)
{
// código para fazer conversão de moeda
}
Os usuários do serviço Web reportam que podem definir uma referência para o
serviço Web, mas o método Convert não está disponível para eles. Qual poderia ser o
problema?
a. O arquivo .asmx para o serviço Web não está disponível no servidor Web.
b. A classe de serviço Web não está marcada com o atributo WebService.
c. O método Convert não está marcado com o atributo WebMethod.
d. Os serviços Web somente podem expor métodos que retornam valores de texto.
10. Você está trabalhando em dois projetos do Visual Studio. O primeiro projeto é um
serviço Web que retorna um objeto DataSet que pertence ao namespace System.Data.
O segundo projeto acessa o serviço Web criado pelo primeiro projeto. Qual projeto
neste cenário requer uma referência ao namespace System.Data?
a. O projeto de serviço Web
b. O projeto de cliente que acessa o serviço Web
c. O projeto de cliente e o projeto de serviço Web
d. Nem o projeto de cliente nem o projeto de serviço Web
■ Avaliação da competência
Cenário 4-1: Usando JavaScript e HTML
Você está desenvolvendo uma página da Web que fornece uma interface de usuário
responsiva. Você decide exibir uma imagem na página. Quando o usuário move o mouse
sobre a imagem, a imagem original é substituída por uma nova. Em seguida, quando
o mouse é movido fora da área de imagem, a imagem original é exibida novamente. Você
espera conseguir isso usando código JavaScript e HTML do lado do cliente. Como você
criaria uma página da Web que funciona como descrito aqui?
■ Avaliação de proficiência
Cenário 4-3: Chamando um serviço Web de maneira assíncrona
A classe proxy gerada pelo Visual Studio para um serviço Web inclui métodos para
chamar o serviço Web de maneira síncrona e assíncrona. Por padrão, o aplicativo usa
o método síncrono. Se você preferir a invocação assíncrona, precisará chamar a versão
assíncrona do método. As versões assíncronas não esperam o serviço Web retornar
uma resposta e usam um mecanismo de retorno de chamada para obter uma resposta
quando ela estiver pronta. A invocação assíncrona de um serviço Web pode ajudar os
aplicativos cliente a serem mais dinâmicos. Se você quiser chamar o método ToLower
do TextWebService criado anteriormente de uma maneira assíncrona. Qual código você
escreveria para invocar de maneira assíncrona um serviço Web?
5 LIÇÃO
Noções básicas
sobre aplicativos da
área de trabalho
M AT R I Z D E H A B I L I D A D E S D A L I Ç Ã O
P R I N C I PA I S T E R M O S
parâmetros de linha de comando instalador Aplicativos do Windows Forms
aplicativo de console Aplicativos MDI (interface de serviço Windows
delegados vários documentos)
eventos herança visual
120
Noções básicas sobre aplicativos da área de trabalho | 121
Um Windows Form é uma superfície visual capaz de exibir vários controles, inclusive
caixas de texto, botões e menus. O Visual Studio fornece o Windows Forms Designer
do tipo “arrastar e soltar” que você pode usar para criar facilmente seus aplicativos.
TOME NOTA
* Para projetar Windows Forms, você deve primeiro decidir quais controles deseja colocar no
Um controle é um formulário. O Windows Forms fornece uma grande coleção de controles comuns que você
elemento distinto de pode usar prontamente para criar uma excelente interface de usuário. Se a funcionalidade
interface do usuário que você está procurando ainda não estiver disponível como um controle comum, você
que aceita a entrada do poderá criar um controle personalizado ou adquirir um controle de outro fornecedor.
usuário ou exibe uma
saída para o usuário. Você pode usar a funcionalidade fornecida pelo Windows Forms Designer do Visual
Studio para inserir e organizar rapidamente os controles de acordo com os seus requisitos.
O Visual Studio fornece acesso fácil aos controles disponíveis através de sua caixa de
ferramentas, como mostra a figura 5-1.
Figura 5-1
Caixa de ferramentas do
Visual Studio
Figura 5-2
Caixa de diálogo Novo Projeto do Visual Studio
Figura 5-3
Windows Form com um
controle DateTimePicker
e um controle Label
5. Selecione Depurar > Iniciar Depuração (ou pressione F5) para executar o projeto.
TOME NOTA
* Na interface de usuário, selecione uma nova data e verifique se a data selecionada
Neste exercício,
é exibida no controle Label.
usamos os nomes de
controle padrão. Em Neste exercício, observe que, quando o formulário é exibido inicialmente, o controle
formulários complexos Label é definido como uma cadeia de caracteres vazia. Depois disso, quando você alterar
com mais controles, a seleção de data, manipulando o controle DateTimePicker, o valor de data selecionada
é recomendável será definido como o texto do controle Label.
atribuir nomes mais
significativos aos
Noções básicas sobre o modelo de evento do Windows Form
controles.
A manipulação de eventos desempenha um papel fundamental na programação
baseada em interface do usuário; através da manipulação de eventos, você pode
responder a vários eventos disparados como resultado de ações do usuário e,
portanto, criar programas interativos. O modelo de evento do Windows Forms
usa delegados do .NET Framework para vincular os eventos aos seus respectivos
manipuladores de eventos.
Nos aplicativos do Windows Forms, cada formulário e controle expõe um conjunto
predefinido de eventos. Quando um evento ocorre, o código no manipulador de evento
associado é invocado. Por exemplo, no exercício anterior, quando você clicou duas vezes
no controle DateTimePicker para adicionar código ao manipulador de eventos, o Visual
Studio gerou o código a seguir para anexar o manipulador de eventos ao evento:
this.dateTimePicker1.ValueChanged +=
new System.EventHandler(
TOME NOTA
* this.dateTimePicker1_ValueChanged);
Um delegado pode ser
Aqui, ValueChanged é o evento do controle DateTimePicker que queremos capturar.
vinculado a qualquer
Portanto, uma nova instância do delegado do tipo EventHandler foi criada, e o método
método cuja assinatura
dateTimePicker1_ValueChanged foi passado para o manipulador de eventos. O método
corresponda à do
dateTimePicker1_ValueChanged é o método no qual você escreve realmente o código de
manipulador de
manipulação de eventos.
eventos.
Esse código é gerado automaticamente pelo Visual Studio Designer. Você encontrará esse
código no arquivo code-behind do designer (Form1.Designer.cs), dentro de uma região de
código intitulada código gerado pelo Windows Form Designer.
Uma outra observação é que a sintaxe para adicionar um delegado usa o operador +=. Isso
porque o .NET Framework oferece suporte a delegados multicast em que um delegado
pode ser vinculado a mais de um método, permitindo, assim, notificações um-para-muitos
quando um evento é disparado.
A herança visual permite que você reutilize funcionalidades e layouts existentes para
Windows Forms.
Um Windows Form, na sua essência, é apenas uma outra classe; portanto, a herança
também se aplica a ele. Entretanto, quando a herança é aplicada a um Windows Form,
ele herda todas as características visuais de um formulário, como tamanho, cor e qualquer
controle localizado no formulário. Você também pode manipular visualmente qualquer
uma das propriedades herdadas da classe base. Portanto, a herança do Windows Forms
é muitas vezes chamada de herança visual. No exercício a seguir, você criará um
Windows Form através da herança visual de um formulário existente.
Figura 5-4
Modelo Formulário Herdado
Noções básicas sobre aplicativos da área de trabalho | 125
Figura 5-5
Caixa de diálogo
Selecionador de Herança
8. Selecione Depurar > Iniciar Depuração (ou pressione F5) para executar o projeto.
Quando InheritedForm for carregado, a data selecionada no momento será exibida no
controle Label. Isso, ao contrário, não ocorre no Form1 criado anteriormente, em que
o controle Label estava inicialmente vazio.
O formulário InheritedForm demonstra que você pode obter toda a funcionalidade de
Form1 simplesmente herdando o formulário. Ao alterar o modificador de acesso dos
controles de membro, label1 e dateTimePicker1, do Form1 de private para protected,
você será capaz de acessá-lo de dentro do formulário herdado. Este exercício também
demonstra como você pode estender a funcionalidade do formulário base em um
formulário herdado.
Figura 5-6
Microsoft Excel 2010 como
um aplicativo MDI
Noções básicas sobre aplicativos da área de trabalho | 127
Figura 5-7
Adicionando opções
de menu
128 | lição 5
O sinal & na frente de um caractere no texto de um menu não é exibido como está;
nesse caso, ele define o caractere como a tecla de atalho do menu. Por exemplo,
*
TOME NOTA o menu &Janela pode ser invocado pressionando Alt+W. As teclas de acesso não
estarão evidentes até que o usuário pressione a tecla Alt. Uma configuração no sistema
operacional Windows controla se as teclas de acesso estarão sempre visíveis.
6. No formulário pai, clique duas vezes no item de menu Janela > Nova Janela e adicione
o seguinte manipulador de eventos para o evento Click:
private void newWindowToolStripMenuItem_Click(
object sender, EventArgs e)
{
ChildForm child = new ChildForm();
child.MdiParent = this;
child.Show();
}
7. No formulário pai, clique duas vezes em Janela > Organizar, Janela > Em Cascata,
Janela > Organizar, Janela > Horizontal e Janela > Organizar, Janela > Vertical,
respectivamente, e adicione os seguintes manipuladores de eventos para seus eventos
Click:
private void cascadeToolStripMenuItem_Click(
object sender, EventArgs e)
{
LayoutMdi(MdiLayout.Cascade);
}
private void horizontalToolStripMenuItem_Click(
object sender, EventArgs e)
{
LayoutMdi(MdiLayout.TileHorizontal);
}
private void verticalToolStripMenuItem_Click(
object sender, EventArgs e)
{
LayoutMdi(MdiLayout.TileVertical);
}
Noções básicas sobre aplicativos da área de trabalho | 129
8. Selecione Depurar > Iniciar Depuração (ou pressione F5) para executar o projeto.
Selecione Janela > Nova Janela para criar várias novas janelas filho. Alterne entre as
janelas filho. Observe que há apenas uma única instância do aplicativo na barra de
tarefas do Windows. Agora, use as opções no menu Janela > Organizar para organizar
as janelas filho. Por exemplo, um aplicativo com três janelas filho pode ser semelhante
à imagem na figura 5-8 quando as janelas filho são organizadas horizontalmente.
Figura 5-8
Um aplicativo MDI com três
janelas filho organizadas
horizontalmente
Vamos rever alguns dos métodos e propriedades importantes usados nesse exercício.
Primeiro, para o formulário pai, a propriedade IsMdiContainer é definida para true.
Essa propriedade indica que a forma é um contêiner de vários formulários filho MDI.
Correspondentemente, para cada formulário filho, você define a propriedade MdiParent
para especificar o formulário do contêiner pai.
Em seguida, a propriedade MdiWindowListItem de MenuStrip é usada para indicar
qual item de menu será usado para exibir a lista de janelas filho MDI. Quando essa
propriedade for definida, o item de menu listará todas as janelas filho e também permitirá
que você alterne entre as janelas filho. Como resultado do código no método ChildForm_
PRONTO PARA
CERTIFICAÇÃO
Load, a barra de título de cada formulário exibirá a data e a hora do instante em que
Você compreende o formulário foi carregado.
como desenvolver Finalmente, o método LayoutMdi é usado pelos itens do menu Janela para organizar as
aplicativos do Windows janelas filho. O método aceita um parâmetro do tipo enumeração MdiLayout. O valor da
Forms?
enumeração determina se as janelas filho precisam estar lado a lado horizontalmente ou
5,1
verticalmente, em cascata ou exibidas como ícones.
Os aplicativos de console não têm uma interface gráfica de usuário e usam uma janela de
O RESULTADO
console no modo texto para interagir com o usuário. Esses aplicativos são mais adequados
a tarefas que não exigem interface do usuário ou exigem uma interface mínima.
TOME NOTA
* Como o nome sugere, um aplicativo de console é executado a partir da janela de console.
Para habilitar a A entrada para esse aplicativo pode ser fornecida usando os parâmetros de linha de
leitura ou a gravação comando, ou o aplicativo pode ler os caracteres da janela de console interativamente.
no console a partir Da mesma forma, a saída de um aplicativo de console também é gravada na janela de
de um aplicativo comando. Você pode habilitar a leitura ou a gravação no console, criando um aplicativo
Windows Forms, por meio do modelo Aplicativo de Console no Visual Studio.
defina o Tipo de Saída
Você também pode usar aplicativos de console para criar comandos que possam ser
do projeto como
executados na linha de comando. Por exemplo, você pode aproveitar os pipes e os filtros
Aplicativo de Console
fornecidos pelo sistema operacional para passar a saída de um comando como entrada
nas Propriedades do
para outro comando, criando, assim, comandos mais avançados através da combinação
projeto.
de comandos simples.
130 | lição 5
O exercício a seguir cria um aplicativo de console simples que aceita o nome de um arquivo
de texto como um argumento de linha de comando e exibe o conteúdo desse arquivo.
Figura 5-9
Modelo Aplicativo
de Console
4. Selecione Compilar > Compilar Solução (ou pressione F6) para compilar o projeto.
5. Crie um arquivo de texto usando o Visual Studio ou o Bloco de Notas, digite um texto
de exemplo e salve o arquivo como Sample.txt na mesma pasta do arquivo executável.
(Por padrão, o arquivo executável é criado na pasta bin\debug sob a pasta do projeto.)
6. Abra um prompt de comando e navegue até o caminho do arquivo EXE do projeto.
Execute o seguinte comando:
DisplayFile sample.txt
PRONTO PARA
CERTIFICAÇÃO Esse comando deve exibir o conteúdo do arquivo de texto na janela de comando.
Você compreende 7. Se preferir, você também poderá passar o argumento de linha de comando do Visual
como desenvolver
Studio usando a janela Propriedades do projeto, como mostra a figura 5-10. Para exibir
aplicativos de console?
a janela Propriedades do projeto, selecione a opção de menu Projeto > Propriedades
5,2
de DisplayFile.
Figura 5-10
Definindo opções de início
na janela Propriedades
do projeto
Um serviço Windows é um aplicativo executado em segundo plano e que não tem uma
O RESULTADO interface de usuário.
A natureza dos serviços Windows torna-os ideais para criar programas de execução
longa que funcionam em segundo plano e não permitem qualquer interação direta do
usuário. Um serviço Windows pode ser iniciado, pausado, reiniciado e parado. Um
serviço Windows também pode ser configurado para começar automaticamente quando
o computador é iniciado.
Alguns exemplos de serviços Windows incluem um servidor Web que escuta as
solicitações de entrada e envia uma resposta ou o spooler de impressão de um sistema
operacional que fornece serviços de impressão para os programas aplicativos.
132 | lição 5
Como um serviço Windows é capaz de ser executado em segundo plano, ele não
precisa que um usuário esteja conectado para funcionar. Os serviços Windows serão
TOME NOTA
* executados em sua própria sessão do Windows no contexto de segurança especificado.
Ainda assim, dependendo das permissões necessárias, você poderá especificar uma
conta de usuário na qual o serviço será executado.
Para criar um serviço Windows no Visual Studio, use o modelo Aplicativo de Serviço
Windows. Observe que um serviço Windows deve ser instalado antes de poder
TOME NOTA
* ser utilizado.
O Visual Studio
Todos os serviços Windows devem derivar da classe ServiceBase. Essa classe base
Express Edition não
fornece a estrutura básica e funcionalidade para criar um serviço Windows. Você pode
fornece modelos
substituir os métodos de classe base OnStart, OnStop, OnPause e OnContinue para
para a criação de
adicionar sua própria lógica personalizada que é executada em resposta às alterações nos
projetos de serviço
estados de serviço.
Windows. Portanto,
você precisará de uma O exercício a seguir demonstra como criar um serviço Windows simples que grava
versão não express mensagens no log de eventos do aplicativo. Os logs de eventos fazem parte do Windows
do Visual Studio para usado por tarefas do sistema operacional e aplicativos em execução em segundo plano
realizar os exercícios para registro de erro ou outras mensagens informativas. Por padrão, o Windows define
que usam projetos de três logs de eventos: Sistema, Aplicativo e Segurança. Os aplicativos geralmente usam
serviço Windows. o log de eventos Aplicativo para registrar sua mensagem. O utilitário Visualizador de
Eventos do Windows pode ser usado para exibir as mensagens em logs de eventos.
8. Selecione Compilar > Compilar Solução (ou pressione F6) para compilar o projeto.
Aqui, o código de FirstService substitui os métodos OnStart, OnStop, OnPause,
OnContinue e OnShutdown para gravar mensagens no log de eventos. No entanto, nem
todos os serviços precisarão substituir esses métodos. A substituição desses métodos por
um serviço dependerá do valor das propriedades CanPauseAndContinue e CanShutdown
de serviço Windows.
O método WriteEntry do log de eventos conduz a mensagem para ser gravada no log,
o tipo de entrada de log de eventos (informações, erro, aviso etc.) e um eventId, que é
uma id específica do aplicativo usada para identificar o evento.
O serviço Windows FirstService agora está pronto, mas antes de ele ser usado, ele deve ser
instalado no banco de dados do serviço Windows. Isso é feito adicionando um instalador
de serviço ao projeto de serviço Windows. O exercício a seguir mostra como fazer isso.
Figura 5-12
Modo de exibição
de Designer para
ProjectInstaller.cs
Noções básicas sobre aplicativos da área de trabalho | 135
Figura 5-13
Usando installutil.exe
TOME NOTA
*
A instalação de um
serviço Windows 4. O serviço Windows FirstService agora está instalado.
requer acesso ao O aplicativo de serviço Windows agora é armazenado no banco de dados de serviço
Registro do Windows. Windows. Anteriormente, quando você adicionou um ServiceInstaller para FirstService,
Portanto, certifique- você definiu a propriedade StartType do componente serviceInstaller1 para Manual. Como
se de instalar resultado, você precisará iniciar o serviço manualmente quando necessário. O exercício
installUtil.exe como a seguir demonstra como iniciar, pausar, continuar e parar um serviço Windows.
administrador.
Figura 5-15
Mensagem de controle de
serviço no início de um
serviço
Figura 5-16
O log Aplicativo Windows
RESUMO DE HABILIDADES
• A
herança visual permite que você reutilize funcionalidades e layouts existentes para
Windows Forms.
• O
s aplicativos MDI (interface de vários documentos) são aqueles em que residem
várias janelas filho sob uma única janela pai.
• O
s aplicativos de console não têm uma interface gráfica de usuário e usam uma
janela de console no modo texto para interagir com o usuário. Esses aplicativos
são mais adequados a tarefas que não exigem interface do usuário ou exigem uma
interface mínima.
• O
s serviços Windows são ideais para criar aplicativos de longa execução que operam
em segundo plano e não têm interface de usuário.
• Você pode criar serviços Windows usando o modelo Serviços Windows do Visual Studio.
• A
ntes de um serviço Windows ser usado, ele deve ser instalado no Registro do
Windows. Para isso, adicione o componente Installer ao aplicativo de serviço
Windows. Isso permitirá que você instale o serviço Windows usando uma ferramenta
de instalação, como InstallUtil.exe.
■ Avaliação de conhecimento
Preencha as lacunas
Complete as sentenças a seguir com a(s) palavra(s) correta(s) nas lacunas fornecidas.
1. Use a propriedade _________ da classe ServiceInstaller para especificar um breve
comentário que explique a finalidade do serviço.
2. A propriedade _________ da classe _________ indica o tipo de conta em que um
serviço Windows será executado.
3. A propriedade _________ da classe EventLog é usada para especificar o nome do
aplicativo a ser usado para gravar em um log de eventos.
4. _________ permite que você reutilize a funcionalidade e o layout existente para o
Windows Forms.
5. Os aplicativos _________ são aqueles em que várias janelas filho residem sob uma
única janela pai.
6. Um(a) _________ é ideal para criar aplicativos de longa execução que operam em
segundo plano e não têm interface de usuário.
7. _________ não tem interface gráfica do usuário e usam uma janela de console em
modo de texto para interagir com o usuário.
8. Os aplicativos _________ fornecem sua própria funcionalidade de gerenciamento de
janela, ao passo que os aplicativos _________ dependem do sistema operacional para
o gerenciamento de janela.
9. Um delegado pode ser vinculado a qualquer método cuja assinatura corresponda à
do(a) _________.
10. O(A) _________ pode ser vinculado(a) a mais de um método, permitindo
notificações um-para-muitos quando um evento é disparado
Noções básicas sobre aplicativos da área de trabalho | 139
Múltipla escolha
Assinale a letra que corresponde à melhor resposta.
1. Você precisa projetar um serviço Windows que não pode ser pausado. Qual das
opções a seguir o ajudará a realizar essa tarefa?
a. Defina a propriedade CanPauseAndContinue do serviço Windows como False.
b. Defina a propriedade CanPauseAndContinue do serviço Windows como True.
c. Defina a propriedade CanStart do serviço Windows como True, mas defina
a propriedade CanShutdown como False.
d. Não substitua os métodos OnPause e OnContinue no serviço Windows.
2. Você desenvolveu um serviço Windows. Você precisa instalar esse serviço para
instalar sua funcionalidade. Qual das opções a seguir você deve escolher para realizar
essa tarefa?
a. Usar o Gerenciador de Servidores do Visual Studio.
b. Usar o nó Serviços na janela Gerenciamento do Computador.
c. Usar o InstallUtil.exe.
d. Usar o gacutil.exe.
3. Você desenvolveu um serviço Windows. Esse serviço precisa ser executado como um
usuário sem privilégios para minimizar qualquer possível risco de segurança. Qual
das seguintes contas você deve usar para executar este serviço Windows?
a. LocalSystem
b. NetworkService
c. LocalService
d. User (em que a propriedade UserName é definida para um membro da função
administrador)
4. Você está projetando um aplicativo de serviço Windows que contém apenas um
serviço Windows. Você deseja que esse serviço seja iniciado automaticamente quando
o computador for reiniciado. Qual das classes a seguir você deve usar para especificar
essa configuração?
a. ServiceBase
b. ServiceInstaller
c. ServiceProcessInstaller
d. ServiceController
5. Você precisa alterar a exibição e o comportamento de um Windows Form para que
ele possa conter várias janelas filho. O que você deve fazer?
a. Definir a propriedade IsMdiContainer do formulário como True.
b. Definir a propriedade MdiParent para todas as janelas filho.
c. Definir a propriedade MdiChild do formulário.
d. Definir a propriedade IsMdiChild do formulário.
6. Você está desenvolvendo um Windows Form que responde aos eventos do mouse.
Quando o mouse se move, você precisa invocar o método Form1_HandleMouse.
Qualquer código escrito não deve afetar nenhum código de manipulação de eventos
existente. Qual instrução você deve usar para anexar o manipulador de eventos ao
evento?
a.
this.MouseDown = new MouseEventHandler
(Form1_HandleMouse);
b.
this.MouseMove = new MouseEventHandler
(Form1_HandleMouse);
140 | lição 5
c.
this.MouseDown += new MouseEventHandler
(Form1_HandleMouse);
d.
this.MouseMove += new MouseEventHandler
(Form1_HandleMouse);
7. Você está desenvolvendo um Windows Form com uma interface MDI. Você precisa
escrever um código que organize as janelas filho verticalmente dentro da região do
cliente do formulário pai MDI. Qual das seguintes instruções você deve usar?
a.
LayoutMdi(MdiLayout.TileVertical);
b.
LayoutMdi(MdiLayout.Cascade);
c.
MdiLayout(LayoutMdi.TileVertical);
d.
MdiLayout(LayoutMdi.Cascade);
8. Você está desenvolvendo um aplicativo que será executado na linha de comando. Qual
dos métodos a seguir você deve usar para gerar a saída para a linha de comando?
a. Console.Read
b. Console.Write
c. File.Read
d. File.Write
9. Você deseja desenvolver um aplicativo que exiba uma superfície visual capaz de
mostrar uma variedade de controles, como caixas de texto, botões e menus. O
aplicativo também deve permitir várias janelas filho sob uma única janela pai. Quais
dos seguintes tipos de aplicativo você deve desenvolver?
a. Aplicativo de console
b. Aplicativo de serviço Windows
c. Aplicativo SDI (Single document interface)
d. Aplicativo MDI (interface de vários documentos)
10. Você está estendendo um aplicativo Windows existente. Você deseja criar um novo
formulário que derive suas características visuais (incluindo tamanho, cor e alguns
controles) de um formulário criado anteriormente. Qual técnica você deve usar para
criar o novo formulário?
a. Herança visual
b. Encapsulamento visual
c. Abstração visual
d. Polimorfismo visual
■ Avaliação da competência
Cenário 5-1: Usando a herança visual
Você precisa criar um Windows Form semelhante ao criado no exercício VisualInheritance.
No entanto, desta vez, o requisito é que a cor de fundo desse formulário coincida com
a cor selecionada no momento na área de trabalho do usuário. Como você desenvolveria
esse formulário?
■ Avaliação de proficiência
Cenário 5-3: trabalhando com a entrada do console
Você está desenvolvendo um programa que manipula texto. Você precisa escrever um
aplicativo de console que aceite texto do usuário e converta-o em letras maiúsculas.
Qual código você precisa escrever para atender a esse requisito?
P R I N C I PA I S T E R M O S
atributo primeira forma normal (1NF) design de banco de dados
DataSet arquivos simples relacional
Um banco de dados permite que você armazene, mantenha e recupere dados importantes.
Se um banco de dados for projetado corretamente, ele poderá ser usado por vários
aplicativos e usuários. Um sistema de gerenciamento de banco de dados (DBMS),
por outro lado, é um software que organiza bancos de dados e fornece recursos, como
armazenamento, acesso a dados, segurança, backup etc. Microsoft SQL Server, Microsoft
Access, Oracle e MySql são exemplos de DBMSs populares.
Os sistemas de gerenciamento de banco de dados podem ser implementados com base
em modelos diferentes. Dentre esses modelos, o modelo relacional é o mais popular. No
modelo relacional, os dados são organizados em tabelas, que podem ter várias linhas.
Os DBMSs com base em modelos relacionais são chamados de DBMSs relacionais
(RDBMSs). SQL Server, Access, Oracle e MySql são todos RDBMSs.
Outros sistemas de gerenciamento de banco de dados são baseados em modelos diferentes.
Por exemplo, os DBMSs (ODBMSs) de objeto baseiam-se no modelo de objeto, em que
os dados são armazenados como uma coleção de objetos. Nesta lição, no entanto, vamos
nos concentrar exclusivamente nos bancos de dados relacionais mais populares.
Os DBMSs relacionais usam a linguagem SQL para recuperar e manipular dados.
Os sistemas de gerenciamento de banco de dados relacional mais populares fornecem
algum suporte para a versão padronizada do SQL, permitindo, assim, que você use suas
habilidades através de diferentes sistemas de banco de dados relacional.
Figura 6-1
Uma tabela Orders em um
banco de dados relacional
144 | lição 6
Os dados de uma organização são um dos seus ativos mais importantes. Assim, quando
você projetar um banco de dados, um dos princípios orientadores será assegurar a
integridade do banco de dados. Integridade significa que os dados no banco de dados são
sempre exatos e consistentes.
O processo de design de um banco de dados consiste nas seguintes etapas:
1. Desenvolver uma declaração de missão para o banco de dados: identifica a
finalidade do banco de dados, como ele será usado e quem o usará. Esta etapa define
o tom do resto do processo de design.
2. Determinar os dados que precisam ser armazenados: identifica todos os tipos
diferentes de dados que precisam ser armazenados no banco de dados. Geralmente,
essas informações são coletadas como parte da tarefa de análise de requisitos, através
de diagramas de relacionamento entre entidades.
3. Dividir os dados em tabelas e colunas: identifica as tabelas e as informações que
você deseja armazenar nessas tabelas.
4. Escolher chaves primárias: uma chave primária é uma coluna ou um conjunto de
colunas que identifica exclusivamente cada linha de dados de uma tabela.
5. Identificar relações: identifica como os dados de uma tabela estão relacionados
com os dados de outra tabela. Por exemplo, para cada cliente de uma tabela Clientes,
você pode ter vários pedidos na tabela Pedidos; essa relação é chamada de relação
um-para-muitos.
6. Aplicar o processo de normalização: aplica regras de normalização de dados para
garantir que qualquer problema que possa afetar a integridade dos dados seja resolvido.
Você aprenderá mais sobre o processo de normalização posteriormente nesta lição.
Após estabelecer a finalidade de um banco de dados, o próximo conjunto de etapas (etapas
2 a 5) poderá ser executado como parte da modelagem de relacionamento entre entidades.
A etapa final de normalização poderá, então, ser aplicada à saída dessa modelagem.
• Relação: uma relação é uma associação entre entidades. Por exemplo, Takes é
um relacionamento entre uma entidade Employee e uma entidade Order (ou seja,
Employee Takes Order).
Observe que os ERDs não mostram entidades únicas ou relações únicas. Por exemplo,
é possível haver milhares de entidades Order e centenas de entidades Customer. Nesse
caso, esses diagramas mostram conjuntos de entidades e conjuntos de relacionamentos —
por exemplo, todas as milhares de entidades Order podem formar um único conjunto de
entidades. Na verdade, quando Order ou Customer aparece em um ERD, ele geralmente
se refere a um conjunto de entidades, e não a uma entidade individual.
Os ERDs usam convenções de design específicas. Em especial:
• Um retângulo representa um conjunto de entidades.
• Uma elipse representa um atributo.
• Um losango representa um conjunto de relacionamentos.
• As linhas sólidas vinculam conjuntos de entidades a conjuntos de relacionamentos e
conjuntos de entidades a atributos.
A figura 6-2 mostra um ERD de exemplo. Neste diagrama, os dois conjuntos de entidades
são Customer e Order. Os atributos associados a Customer são ID, Name e City. Os
atributos associados a Order são OrderID, OrderDate e ShipDate. Esses atributos que
formam uma chave primária são sublinhados. Além disso, conforme mostrado na figura, o
relacionamento entre Customer e Order é Places.
Figura 6-2
Um diagrama de
relacionamento entre
entidades
Quando mapeado para um banco de dados relacional, o ERD da figura 6-2 gera as tabelas
a seguir:
Customers
ID Name City
1001 Jane Doe Berlin
1002 John Doe Tokyo
1003 Howard Steel Sydney
Orders
A análise do relacionamento entre entidades ajuda a garantir sua identificação dos itens de
dados corretos para seu banco de dados. Em seguida, através do processo de normalização
de dados, você aplica um conjunto de regras de normalização para se certificar de que
tenha estabelecido o design de banco de dados correto — ou seja, você verifica se as
colunas pertencem às tabelas certas para garantir que seu banco de dados esteja livre de
problemas indesejáveis.
Por exemplo, como parte da análise do relacionamento entre entidades, você pode
encontrar uma tabela Livros com as seguintes colunas:
Books
TOME NOTA
* Id FirstName LastName PhoneNumber
Uma convenção geral
consiste em sublinhar 1 Jane Doe (503) 555-6874
os nomes das colunas 2 John Doe (509) 555-7969,
em uma tabela que (509) 555-7970
fazem parte da chave
primária. 3 Howard Steel (604) 555-3392,
(604) 555-3393
Id FirstName LastName
1 Jane Doe
2 John Doe
3 Howard Steel
CustomerPhones
Id PhoneNumber
1 (503) 555-6874
2 (509) 555-7969
2 (509) 555-7970
3 (604) 555-3392
3 (604) 555-3393
148 | lição 6
2NF aplica-se somente a tabelas com chaves primárias compostas (ou seja, várias
colunas juntas compõem a chave primária). Os valores combinados de todos os campos
*
TOME NOTA em uma chave primária composta devem ser exclusivos. Se uma tabela atender à
1NF e tiver apenas uma única coluna em sua chave primária, ela também estará em
conformidade com a 2NF.
Por outro lado, considere a tabela a seguir:
Orders
Aqui, as colunas OrderId e CustomerId juntas identificam uma linha exclusiva e, portanto,
formam uma chave primária composta. No entanto, a coluna OrderDate é funcionalmente
dependente apenas de OrderId, e a coluna CustomerName é dependente apenas de
CustomerId. Isso viola 2NF, pois as colunas que não são de chave são funcionalmente
dependentes apenas de parte da chave primária.
Uma maneira possível de modificar a tabela Orders para que ela fique em conformidade
com 2NF é retirar CustomerName da tabela e ter apenas três colunas — OrderId,
CustomerId e OrderDate — com apenas OrderId funcionando como chave primária. Nessa
solução, tanto CustomerId quanto OrderDate são funcionalmente dependentes de OrderId
e, portanto, estão em conformidade com 2NF.
Noções básicas sobre bancos de dados | 149
ItemId SupplierId
101 100
102 11
103 525
Supplier
PRONTO PARA
CERTIFICAÇÃO
Você compreende SupplierId ReorderFax
as noções básicas
dos sistemas de 100 (514) 555-2955
gerenciamento de
banco de dados 11 (514) 555-9022
relacional? 525 (313) 555-5735
6,1
SQL é a linguagem usada pela maioria dos sistemas de banco de dados para gerenciar as
informações em seus bancos de dados. Os comandos SQL permitem que você recupere e
atualize dados. Os comandos SQL também permitem que você crie e gerencie objetos de
banco de dados, como tabelas. A linguagem SQL pode ser considerada uma linguagem de
programação para bancos de dados relacionais. No entanto, ela é declarativa, por natureza,
em oposição à natureza imperativa das linguagens de programação mais comuns.
150 | lição 6
Em SQL, você informa ao banco de dados o que precisa ser feito, e é função do banco
de dados descobrir como fazer isso — por exemplo, você pode dizer ao banco de dados
para selecionar as 10 primeiras linhas de uma tabela. Compare isso com uma linguagem
de programação imperativa, como C#, em que você precisa especificar em detalhes como
o trabalho deve ser realizado. Por exemplo, você pode precisar criar um loop que seja
executado dez vezes, configurar e inicializar variáveis, mover ponteiros de registro etc.
SQL é um padrão ANSI (American National Standards Institute), mas diferentes
fornecedores de banco de dados implementaram suas próprias extensões ao SQL padrão.
A implementação do Microsoft SQL Server é denominada T-SQL (Transact-SQL).
Há duas maneiras principais de enviar T-SQL para o SQL Server. Você pode usar
instruções SQL ad hoc executadas diretamente ou usar procedimentos armazenados. Os
procedimentos armazenados são coleções de instruções SQL e lógica de programação
armazenadas no servidor de banco de dados como objetos nomeados.
Trabalhando com consultas SQL
O uso de consultas SQL ad hoc é uma maneira flexível de trabalhar com um banco de
dados SQL Server. Nesta parte da lição, você aprenderá as noções básicas sobre os quatro
tipos principais de instruções SQL que o ajudarão a manipular dados do SQL Server:
• As instruções SELECT permitem que você recupere dados armazenados em um
banco de dados.
• As instruções INSERT permitem que você adicione novos dados a um banco de dados.
• As instruções UPDATE permitem que você modifique os dados existentes em um
banco de dados.
• As instruções DELETE permitem que você exclua dados de um banco de dados.
Neste exercício, você aprenderá a trabalhar com um banco de dados Microsoft SQL
Server. Se não tiver acesso a uma versão recente do SQL Server, você poderá baixar o
SQL Server 2008 Express gratuitamente de http://www.microsoft.com/pt-br/server-cloud/
products/sql-server-editions/sql-server-standard.aspx. Este exercício usa o banco de dados
SQL Server de exemplo Northwind. Esse banco de dados não é instalado, por padrão, com
o SQL Server, mas você pode baixar o arquivo de banco de dados seguindo as instruções
em http://msdn.microsoft.com/pt-br/library/ms143221.aspx.
Execute o exercício a seguir para se conectar ao banco de dados Northwind e usá-lo com
o Visual Studio.
Figura 6-3
Conectando ao banco de
dados Northwind
Figura 6-4
Acessando o banco de
dados Northwind através do
Gerenciador de Servidores
152 | lição 6
Figura 6-5
Janela Propriedades do
banco de dados Northwind
bancos de dados.
Há várias maneiras de enviar consultas para um SQL Server. Por exemplo, você pode usar
qualquer um destes:
• IDE (ambiente de desenvolvimento integrado) do Visual Studio
• Aplicativo C#
• SQL Query Analyzer
• utilitário de prompt de comando osql
Observe que os utilitários de prompt de comando SQL Query Analyzer e osql são
ferramentas instaladas com o SQL Server.
PREPARE-SE. Para usar os aplicativos C# e IDE do Visual Studio para executar consultas
SQL, siga estas etapas:
1. Selecione o banco de dados Northwind no Gerenciador de Servidores. Clique com o botão
direito do mouse no banco de dados e selecione Nova Consulta. Essa ação abre um
Designer de Consultas e mostra uma caixa de diálogo Adicionar Tabela. Selecione a tabela
Clientes e clique em Adicionar. Clique em Fechar na caixa de diálogo Adicionar Tabela.
2. No painel SQL do Designer de Consultas (que é a área que exibe o texto da consulta),
modifique a instrução SQL para:
SELECT * FROM Customers
3. No menu do Visual Studio, selecione a opção Designer de Consultas > Executar
SQL ou clique no botão Executar SQL na barra de ferramentas. A instrução SQL será
enviada para o servidor SQL para execução, e é possível que resultados como os da
figura 6-6 sejam exibidos.
Noções básicas sobre bancos de dados | 153
Figura 6-6
Designer de Consultas do
Visual Studio
O Designer de Consultas no Visual Studio exibe até quatro painéis. Os painéis são os
seguintes, de cima para baixo:
• Painel Diagrama: esse painel exibe as tabelas envolvidas na consulta e os
relacionamentos entre essas tabelas, bem como todas as colunas contidas nas tabelas.
• Painel Critérios: esse painel mostra as colunas que foram selecionadas como parte
da consulta, bem como informações adicionais de classificação e filtragem.
• Painel SQL: esse painel mostra a real instrução SQL que será executada.
• Painel Resultados: esse painel mostra os resultados (se houver) depois que
a consulta tiver sido executada.
A barra de ferramentas Designer de Consultas inclui botões que você pode usar para
ocultar ou mostrar qualquer um desses quatro painéis. Para o exercício a seguir, você
precisará apenas do painel SQL e do painel Resultados.
Figura 6-7
Consultas em execução de
um aplicativo C#
Noções básicas sobre bancos de dados | 155
A instrução SELECT é usada para recuperar dados de uma ou mais tabelas de banco
de dados.
A instrução SELECT geralmente tem a seguinte forma:
SELECT list_of_fields
FROM list_of_tables
WHERE where_clause
GROUP BY group_by_clause
HAVING having_clause
ORDER BY order_by_clause
Cada uma dessas linhas de código na instrução SELECT é chamada de cláusula. As
cláusulas SELECT e FROM são necessárias, mas o restante é opcional. Por exemplo, esta
é uma instrução SQL que contém apenas as cláusulas necessárias:
SELECT OrderId, CustomerId
FROM Orders
Se quiser listar todos os campos de uma tabela, você também poderá usar o atalho a
seguir, em vez de listar explicitamente todos os campos:
SELECT *
FROM Orders
Além disso, você pode selecionar informações de várias tabelas; por exemplo:
Select OrderId, Customers.CustomerId, ContactName
From Orders, Customers
Customers.CustomerId é conhecido como um nome totalmente qualificado por especificar
o nome da tabela e o nome do campo. Isso é necessário porque as tabelas Orders e
Customers incluem esse campo, portanto, você deve informar ao SQL Server à qual tabela
específica você deseja se referir.
Se executar essa consulta, você terá muito mais registros do que o esperado. Isso acontece
porque, embora tenha informado ao SQL Server quais tabelas incluir, você não inseriu
qualquer informação sobre como relacionar essas tabelas. Como resultado, o SQL Server
constrói o conjunto de resultados para incluir todas as linhas da tabela Customer para cada
linha da tabela Orders. Este tipo de junção é chamado de junção cruzada e, nesse caso,
não é muito útil.
Uma consulta mais útil, é claro, faria a correspondência de cada pedido com o respectivo
cliente. A palavra-chave INNER JOIN pode ajudá-lo a fazer isso, como mostrado na
consulta a seguir:
SELECT OrderID, Customers.CustomerId, ContactName
FROM Orders INNER JOIN Customers
ON Orders.CustomerId = Customers.CustomerId
156 | lição 6
Essa consulta informa ao SQL Server para fazer a correspondência de cada linha da
tabela Orders com todas as linhas da tabela Customers em que o CustomerId do pedido é
igual ao CustomerId do cliente. Como CustomerId é exclusivo na tabela Customers, isso
equivale a incluir apenas uma única linha para cada pedido no conjunto de resultados.
Neste caso, o conjunto de resultados terá o mesmo número de linhas que o número de
linhas existentes na tabela Orders.
Mas, e se você quiser ver apenas algumas linhas da tabela? Nessa situação, você poderá
TOME NOTA
* usar a cláusula WHERE. A cláusula WHERE avalia cada linha para uma condição e
O delimitador padrão
decide se a incluirá no conjunto de resultados. Por exemplo:
para texto e datas no
SQL Server é a aspa SELECT *
simples. FROM Orders
WHERE ShipCountry = 'Canada'
Aqui, a cláusula WHERE examina todas as linhas da tabela Orders para ver se
ShipCountry tem o valor exato “Canada”. Se isso acontecer, a linha será incluída no
conjunto de resultados; caso contrário, a linha não será incluída no conjunto de resultados.
Você também pode combinar várias condições em uma única cláusula WHERE. Por
exemplo:
SELECT *
FROM Orders
WHERE (ShipCountry = 'Canada')
AND (OrderDate >= '01/01/97')
AND (OrderDate <= '01/31/97')
Aqui, as condições WHERE filtram os pedidos em que ShipCountry é “Canada” e a data
do pedido é janeiro de 1997.
Por padrão, o SQL não garante que os resultados estejam em uma ordem específica. No
entanto, você pode usar a cláusula ORDER BY para garantir que os dados desejados
sejam retornados em uma ordem específica. Por exemplo, para listar os pedidos com base
na data do pedido, você pode usar a seguinte consulta:
SELECT *
FROM Orders
WHERE (ShipCountry = 'Canada')
AND (OrderDate >= '01/01/97')
AND (OrderDate <= '01/31/97')
ORDER BY OrderDate
Você pode modificar a ordem de classificação, usando a palavra-chave ASC (para
ordem crescente) ou DESC (para ordem decrescente). A ordem de classificação padrão
é crescente. Portanto, a consulta a seguir lista os pedidos mais recentes na parte superior:
SELECT *
FROM Orders
WHERE (ShipCountry = 'Canada')
AND (OrderDate >= '01/01/97')
AND (OrderDate <= '01/31/97')
ORDER BY OrderDate DESC
Noções básicas sobre bancos de dados | 157
Na instrução SQL anterior, Count é uma função de agregação, ou seja, ele retorna um
resultado com base em um grupo de linhas. T-SQL oferece suporte várias funções de
agregação diferentes. Algumas das mais comuns são:
• Count: retorna o número de registros
• Sum: retorna o valor total em uma determinada coluna
• Avg: retorna o valor médio em uma determinada coluna
• Min: retorna o menor valor em uma determinada coluna
• Max: retorna o maior valor em uma determinada coluna
ATUALIZAÇÃO DE DADOS
A instrução UPDATE é usada para atualizar informações nas tabelas de banco de dados.
Nessa consulta, a palavra-chave SET informa ao SQL Server quais colunas atualizar,
TOME NOTA
* e a palavra-chave WHERE informa a ele quais linhas atualizar. Na tabela Customers,
Em uma instrução CustomerId é uma chave primária e é identificada exclusivamente por uma única linha.
UPDATE, a cláusula Portanto, essa instrução UPDATE pode atualizar, no máximo, uma linha.
SET é necessária
e pode ser especificada Observe, no entanto, que você não está limitado a atualizar apenas um único registro.
apenas uma vez. Pelo contrário, se a cláusula WHERE selecionar vários registros, todos esses registros
serão atualizados:
UPDATE Customers
TOME NOTA
* SET Country = 'United States'
É altamente WHERE Country = 'USA'
recomendável
que você examine Você também pode atualizar mais de um campo por vez com uma instrução UPDATE,
cuidadosamente como no exemplo a seguir:
a cláusula WHERE UPDATE Customers
para cada instrução
SET ContactName = 'Maria Anderson',
UPDATE. Se não tiver
cuidado, você poderá CITY = 'Tokyo'
atualizar dados para WHERE CustomerId = 'ALFKI'
mais linhas do que
o desejado.
INSERÇÃO DE DADOS
A instrução INSERT é usada para adicionar uma ou mais linhas a uma tabela de
banco de dados.
A instrução INSERT lista os campos para a tabela de destino, seguidos por um conjunto
de valores para inserir nesses campos. Por exemplo, a instrução INSERT a seguir insere
uma linha na tabela Order Details:
INSERT INTO [Order Details]
(OrderId, ProductId, UnitPrice, Quantity, Discount)
VALUES (10248, 2, 19.00, 2, 0)
Colchetes são necessários quando os nomes de tabelas ou campos contêm espaços. Aqui,
o primeiro conjunto de parênteses contém uma lista de colunas, e o segundo conjunto
contém os valores a serem inseridos. Se um campo tiver um valor padrão, puder ser nulo
ou for um campo de identidade, você poderá deixá-lo fora da lista de campos, como no
exemplo a seguir:
INSERT INTO [Order Details]
(OrderId, ProductId, UnitPrice, Quantity)
VALUES (10249, 2, 19.00, 2)
Essa instrução funcionará mesmo que nenhum valor tenha sido especificado para o campo
Discount. Além disso, com essa instrução, você poderá reorganizar uma lista de campos
desde que reorganize a lista de valores para correspondência:
INSERT INTO [Order Details]
(ProductId, OrderId, UnitPrice, Quantity)
VALUES (2, 10250, 19.00, 2)
A instrução INSERT não se limita à inserção de um único registro. Na verdade, há um
segundo formato que insere os resultados de uma instrução SELECT na tabela de destino.
Por exemplo, esta consulta insere um produto de cada fornecedor na tabela Products:
INSERT INTO Products
(SupplierId, ProductName, CategoryId)
SELECT SupplierId, 'Almond', 7
FROM Suppliers
Noções básicas sobre bancos de dados | 159
EXCLUSÃO DE DADOS
A instrução DELETE é usada para remover informações das tabelas de banco de dados.
A instrução DELETE remove dados de uma tabela. Para fins de prática e para evitar a
exclusão de dados do mesmo banco de dados, você poderá copiar uma tabela usando uma
instrução SELECT, como no exemplo a seguir:
SELECT * INTO CustomersCopy
FROM Customers
Essa instrução seleciona todos os registros da tabela Customers e copia-os para uma nova
tabela denominada CustomersCopy.
Para excluir uma única linha de dados da tabela CustomersCopy, você usaria a seguinte
instrução DELETE:
DELETE FROM CustomersCopy
WHERE CustomerId = 'ALFKI'
Tenha cuidado, pois se omitir a cláusula WHERE, você excluirá todos os dados da tabela:
DELETE FROM CustomersCopy
AS
SELECT @TotalSales = SUM(Quantity * UnitPrice)
FROM (Customers INNER JOIN Orders
ON Customers.CustomerId = Orders.CustomerId)
INNER JOIN [Order Details]
ON Orders.OrderId = [Order Details].OrderId
WHERE Customers.CustomerId = @CustomerId
RETURN
3. Salve o procedimento armazenado. O procedimento armazenado é agora adicionado
ao banco de dados.
Nesse procedimento armazenado, @CustomerId e @TotalSales são parâmetros.
@CustomerId é um parâmetro de entrada; você deverá fornecer um valor para esse
parâmetro ao executar o procedimento armazenado. @TotalSales é um parâmetro de
saída; ele retorna um valor do procedimento armazenado. Ao executar esse procedimento
armazenado do Visual Studio, você recebe uma caixa de diálogo solicitando a inserção do
valor para todos os parâmetros, conforme mostra a figura 6-9.
Figura 6-9
A caixa de diálogo Executar
Procedimento Armazenado
solicita os valores de
parâmetro
3. Clique duas vezes no controle Button para gerar um manipulador de eventos para
o evento Click. Modifique o manipulador de eventos, como mostrado abaixo:
private void GetTotalSalesButton_Click(
object sender, EventArgs e)
{
TotalSalesLabel.Text = String.Format(
"Total Sales: {0}",
GetTotalSales(CustomerIdTextBox.Text));
}
4. Adicione o método a seguir à classe. Certifique-se de alterar a cadeia de caracteres
de conexão para corresponder ao caminho local do arquivo de banco de dados no
seu computador:
private double GetTotalSales(string customerId)
{
double totalSales = −1;
try
{
// Altere a cadeia de conexão
// de acordo com seu sistema.
string connectionString =
@"Data Source=.\SQLEXPRESS;" +
@"AttachDbFilename=" +
@"c:\SqlSampleDB\NORTHWND.MDF;" +
@"Integrated Security=True;" +
@"Connect Timeout=30;User Instance=True";
SqlConnection connection =
new SqlConnection(connectionString);
SqlCommand command =
connection.CreateCommand();
command.CommandType =
CommandType.StoredProcedure;
command.CommandText = "GetCustomerSales";
command.Parameters.AddWithValue(
"@CustomerId", customerId);
command.Parameters.AddWithValue(
"@TotalSales", null);
command.Parameters["@TotalSales"].DbType
= DbType.Currency;
command.Parameters["@TotalSales"].Direction
= ParameterDirection.Output;
connection.Open();
command.ExecuteNonQuery();
Noções básicas sobre bancos de dados | 163
totalSales = Double.Parse(
command.Parameters["@TotalSales"]
.Value.ToString());
connection.Close();
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
return totalSales;
}
5. Adicione as diretivas using a seguir ao código:
using System.Data;
using System.Data.SqlClient;
Selecione Depurar > Iniciar Depuração para executar o projeto. Insira um CustomerId
válido. Você deverá ver a saída mostrada na figura 6-10.
Figura 6-10
Executando procedimentos
armazenados parametrizados
de um aplicativo C#
Se adicionar uma nova linha a uma tabela com uma coluna de identidade, você poderá
*
TOME NOTA usar a variável @@IDENTITY do SQL Server para recuperar o valor da coluna de
identidade para a linha recém-criada.
C# também fornece uma instrução using que pode ajudar a assegurar que objetos dispendiosos,
TOME NOTA
* como conexões de banco de dados, sejam fechados automaticamente quando você terminar de
O objeto usado com a usá-los. Aqui está uma versão alternativa do código acima que utiliza a instrução using para
instrução using deve fechar automaticamente a conexão de banco de dados:
implementar a interface
IDisposable. // descartando objetos com a instrução using
using (connection)
PRONTO PARA {
CERTIFICAÇÃO connection.Open();
Você compreende os
vários métodos de command.ExecuteNonQuery();
consulta de banco de totalSales = Double.Parse(
dados?
command.Parameters["@TotalSales"]
.Value.ToString());
PRONTO PARA }
CERTIFICAÇÃO
Você compreende Observe que a instrução using define um escopo para o objeto de conexão. Quando o código
o que são métodos de atinge o final desse escopo, o objeto de conexão é automaticamente fechado, e todos os
conexão de banco de recursos são liberados.
dados?
6,3
O .NET Framework fornece classes que são otimizadas para trabalhar com arquivos simples,
arquivos XML e objetos na memória. Os dados armazenados dentro de arquivos simples podem
ser manipulados usando as classes do namespace System.IO. Para trabalhar com dados XML,
as classes do namespace System. XML podem ser usadas. Finalmente, para trabalhar com
objetos na memória, como um DataSet, são usadas as classes do namespace System.Data. Você
aprenderá mais sobre como trabalhar com cada um desses formatos de dados nas seções a seguir.
Trabalhando com arquivos simples
Um arquivo simples geralmente contém uma linha de dados por linha, e as colunas são separadas
por delimitadores, como vírgulas ou têm um comprimento fixo. Os dados em um arquivo simples
podem ser texto ou binário. Esses arquivos são chamados de “arquivos simples” para distingui-
los das formas mais estruturadas de armazenamento, tais como bancos de dados relacionais e
arquivos XML.
Historicamente, antes do advento dos bancos de dados modernos, os arquivos simples eram uma
maneira popular para armazenar e organizar informações. Eles ainda são úteis atualmente, embora
somente em cenários limitados, ao contrário dos bancos de dados para uso geral. Os arquivos
simples são utilizados no sistema operacional ou nos arquivos de configuração de aplicativo,
ao transferir dados para sistemas remotos e na migração de dados entre sistemas incompatíveis.
A entrada e a saída baseadas em arquivo no .NET Framework giram em torno do conceito de
streams e repositório de backup. Um stream é um fluxo de dados brutos, e um repositório de
backup é a origem ou o destino do stream. Um repositório de backup pode ser um arquivo de
disco, memória, conexão de rede etc. Você poderá encontrar classes para trabalhar com streams
e repositórios de backup no namespace System.IO.
Noções básicas sobre bancos de dados | 165
command.CommandText =
"SELECT CustomerId, CompanyName,"
+ "ContactName, Phone FROM Customers";
using (connection)
{
connection.Open();
SqlDataReader reader =
command.ExecuteReader();
using (StreamWriter sw =
new StreamWriter(fileName))
{
while (reader.Read())
{
string customerRow =
String.Format("{0}, {1}, {2}, {3}",
reader.GetValue(0),
reader.GetValue(1),
reader.GetValue(2),
reader.GetValue(3));
sw.WriteLine(customerRow);
}
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
static void DisplayTextFile(string fileName)
{
try
{
using (StreamReader sr =
new StreamReader(fileName))
{
string line;
while ((line = sr.ReadLine()) != null)
{
Console.WriteLine(line);
}
}
}
Noções básicas sobre bancos de dados | 167
Em XML, você pode armazenar dados e metadados (informações sobre os dados que
estão sendo armazenados). Por exemplo, a linguagem XML a seguir representa os dados
de dois clientes:
<?xml version="1.0" encoding="utf-8"?>
<!--Customer List-->
<Customers>
<Customer Id="ALFKI">
<CompanyName>Alfreds Futterkiste</CompanyName>
<Phone>030-0074321</Phone>
</Customer>
<Customer Id="EASTC">
<CompanyName>Eastern Connection</CompanyName>
<Phone>(171) 555-0297</Phone>
</Customer>
</Customers>
Mesmo sem saber nada sobre XML, você conseguirá compreender o conteúdo desse arquivo
apenas olhando para ele. A linguagem XML é composta por marcas (contidas dentro de
colchetes angulares) e dados. As marcas sempre aparecem em pares, com cada marca de
abertura acompanhada por uma marca de fechamento. Por exemplo, <Customers> é uma
marca de abertura e </Customers> é a marca de fechamento correspondente.
A primeira linha de um documento XML é a declaração XML:
<?xml version="1.0" encoding="utf-8"?>
As marcas XML que começam com <? são chamadas de instruções de processamento.
Essa instrução de processamento nos diz que o documento é um XML em conformidade
com as especificações da linguagem XML versão 1.0 e usa o conjunto de caracteres
UTF-8 para seus elementos de dados.
168 | lição 6
Uma marca de abertura e uma marca fechamento junto com seu conteúdo são chamados
de elemento. Por exemplo, a seguir é apresentado um único elemento XML do documento
acima:
<Phone>030-0074321</Phone>
Esse bit de código define um elemento com o nome Phone cujo valor é 030-0074321. Os
elementos podem ser aninhados, mas não podem se sobrepor. Por exemplo, a linguagem
XML a seguir é inválida devido à sobreposição entre os elementos CompanyName e
Phone:
<Customer Id="EASTC">
<CompanyName>Eastern Connection<Phone>
</Phone>(171) 555-0297</CompanyName>
</Customer>
</Customers>
Os documentos XML são hierárquicos por natureza. Cada documento XML contém um
único elemento raiz com todos os outros nós. Portanto, um documento XML pode ser
visualizado como uma árvore de nós.
Os elementos podem conter atributos. Um atributo é um determinado dado que descreve
um elemento em mais detalhes. Por exemplo:
<Customer Id="ALFKI">
Aqui, o elemento Customer inclui um atributo cujo nome é Id e cujo valor é ALFKI.
Finalmente, um documento XML pode conter comentários. Os comentários começam com
os caracteres <!-- e terminam com os caracteres -->.
A linguagem XML muitas vezes é mais complexa do que o que é discutido nesta seção.
No entanto, essas noções básicas são suficientes para você compreender a maioria dos
documentos XML que provavelmente desejará executar até começar a trabalhar com XML
de forma aprofundada.
Há várias maneiras de trabalhar com dados XML. As classes que trabalham com dados
XML são organizadas no namespace System.Xml. Esta parte da lição concentra-se nas
seguintes classes comumente usadas:
• XmlReader e XmlWriter: essas classes fornecem uma maneira rápida, sem
armazenamento em cache e somente de encaminhamento para ler ou gravar dados XML.
• XmlDocument: essa classe é uma representação na memória de dados XML e
permite a navegação e a edição do documento XML.
No exercício a seguir, você poderá usar a classe XmlReader para ler o nome de arquivo
XML Customers.xml de maneira sequencial e somente de encaminhamento.
if (reader.IsStartElement())
{
switch (reader.Name)
{
case "CompanyName":
if (reader.Read())
{
Console.Write(
"Company Name: {0}, ",
reader.Value);
}
break;
case "Phone":
if (reader.Read())
{
Console.WriteLine(
"Phone: {0}", reader.Value);
}
break;
}
}
}
}
3. Em seguida, adicione a diretiva using a seguir ao programa:
using System.Xml;
4. Agora, adicione um novo arquivo XML denominado Customers.xml ao projeto.
Verifique se o arquivo xml contém estes dados:
<?xml version="1.0" encoding="utf-8"?>
<!--Customer List-->
<Customers>
<Customer Id="ALFKI">
<CompanyName>Alfreds Futterkiste</CompanyName>
<Phone>030-0074321</Phone>
</Customer>
<Customer Id="EASTC">
<CompanyName>Eastern Connection</CompanyName>
<Phone>(171) 555-0297</Phone>
</Customer>
</Customers>
Compile o programa. Copie o arquivo Customers.xml para a pasta do programa
executável. Execute o programa. Você deverá ver uma lista de todos os nomes de
empresa e números de telefone.
170 | lição 6
O código neste exercício primeiro cria uma nova instância de XmlReader usando o método
XmlReader.Create. Isso gerará uma exceção se o arquivo não for encontrado. O programa
será encerrado quando o método XmlReader.Read não tiver nada para ler. Você pode usar
propriedades, como Name e Value, para acessar várias partes da linguagem XML.
Você também pode se conectar a um banco de dados do SQL Server usando as classes
OdbcAdapter e OleDbAdapter. No entanto, a classe SQLDataAdapter é otimizada
*
TOME NOTA
para o SQL Server. Portanto, quando se trabalha com o SQL Server, é preferível usar a
classe SQLDataAdapter.
Um DataSet pode ler e gravar dados como documentos XML. Para gravar dados como
*
TOME NOTA XML, use o método WriteXml da classe DataSet. Para ler dados do documento XML,
use o método ReadXml da classe DataSet.
Noções básicas sobre bancos de dados | 173
RESUMO DE HABILIDADES
■ Avaliação de conhecimento
Preencha as lacunas
Complete as sentenças a seguir com a(s) palavra(s) correta(s) nas lacunas fornecidas.
1. Para que uma tabela esteja na _______________, nenhuma das colunas deve ter
vários valores na mesma linha de dados.
2. A _______________ exige que todas as colunas que não são de chave sejam
funcionalmente dependentes de toda a chave primária.
3. A _______________ exige que não haja dependência funcional entre os atributos que
não são de chave.
4. Os blocos de construção básicos para um diagrama de relacionamento entre entidades
são _______________, _______________ e _______________.
5. A cláusula _______________ em uma instrução SELECT avalia cada linha para uma
condição e decide se deve incluí-la no conjunto de resultados.
6. O objeto usado com a instrução using deve implementar a interface
_______________.
7. A instrução _______________ de T-SQL pode ser usada para criar um procedimento
armazenado.
174 | lição 6
Múltipla escolha
Assinale a letra que corresponde à melhor resposta.
1. Seu aplicativo precisa armazenar a imagem do produto em um arquivo de disco. Você
gostaria de minimizar o tamanho deste arquivo de disco. Qual dos seguintes objetos você
deve usar para escrever o arquivo?
a. FileStream
b. StreamWriter
c. BinaryWriter
d. XmlWriter
2. Seu programa em C# precisa retornar o número total de clientes em um banco de dados.
O programa será usado várias vezes ao dia. Qual é o caminho mais rápido para retornar
essas informações de seu programa?
a. Escrever uma consulta SQL e use o método SqlCommand.ExecuteScalar para executar
a consulta.
b. Criar um procedimento armazenado para retornar o número total de clientes e, em
seguida, usar o método SqlCommand.ExecuteScalar para executar o procedimento
armazenado.
c. Escrever uma consulta SQL e use o método SqlDataAdapter.Fill para executar a con-
sulta.
d. Criar um procedimento armazenado para retornar o número total de clientes e, em
seguida, usar o método SqlDataAdapter.Fill para executar o procedimento armazenado.
3. Você precisa modificar os registros em uma tabela de produtos, marcando determinados
produtos como descontinuados. No entanto, você precisa fazer isso somente quando
UnitsInStock e UnitsOnOrder estiverem ambos zero. Qual das seguintes instruções SQL
você deve usar?
a. INSERT
b. SELECT
c. UPDATE
d. DELETE
4. Você precisa atualizar os campos da região para clientes no Japão. Você escreve a
seguinte instrução SQL UPDATE:
UPDATE Customers
SET Region = 'EastAsia'
Você testa a consulta em um banco de dados de teste e descobre que mais registros foram
afetados do que você esperava. Você precisa corrigir a instrução SQL. O que você deve fazer?
a. Adicione uma cláusula WHERE à instrução UPDATE.
b. Adicione uma cláusula SET adicional à instrução UPDATE.
c. Adicione uma cláusula GROUP BY à instrução UPDATE.
d. Adicione uma cláusula HAVING à instrução UPDATE.
5. Você está desenvolvendo um aplicativo que precisa recuperar uma lista de clientes de um
banco de dados do SQL Server. O aplicativo deve percorrer a lista sequencialmente uma
vez, processando o registro de cada cliente. Qual das seguintes classes você deve usar para
manter a lista de clientes a fim de alcançar o desempenho máximo?
a. DataSet
b. DataTable
c. DataView
d. SqlDataReader
Noções básicas sobre bancos de dados | 175
6. O aplicativo que você está desenvolvendo precisa ler dados de um arquivo simples
que inclua itens como, por exemplo, uma chave de inteiros de cinco dígitos, seguido
por um nome de cliente de 20 caracteres e dois campos de data e hora. Qual das
seguintes classes você deve usar?
a. FileStream
b. StreamReader
c. BinaryReader
d. DataReader
7. Você está desenvolvendo um aplicativo que precisará copiar dados de uma exibição
do SQL Server para um DataSet. Você dá ao objeto DataSet o nome de dsData. Qual
dos métodos a seguir você deve usar para copiar os dados?
a. Fill
b. InsertCommand
c. SelectCommand
d. Update
8. Você está desenvolvendo um aplicativo que gerencia os clientes e seus pedidos.
Qual das seguintes situações não é um bom candidato para implementação com
procedimentos armazenados em seu aplicativo?
a. Recuperar a lista de todos os clientes no banco de dados
b. Recuperar a lista de todos os pedidos para clientes específicos
c. Inserir um novo pedido na tabela Orders
d. Consulta ad hoc pelo administrador de banco de dados
9. Seu aplicativo conecta-se a um banco de dados do SQL Server que contém uma
tabela chamada Employees com as seguintes colunas:
EmployeeID (int, identity)
EmployeeType (char(1))
EmployeeDate (datetime)
Você precisa escrever uma consulta que exclui todas as linhas da tabela onde o
valor de EmployeeType é C ou T. Você não quer excluir todas as outras linhas. Que
instrução você deve usar?
a. DELETE FROM Employees
WHERE EmployeeType LIKE '[CT]'
b. DELETE FROM Employees
WHERE EmployeeType LIKE '[C-T]'
c. DELETE FROM Employees
WHERE EmployeeType LIKE 'C' OR 'T'
d. DELETE * FROM Employees
WHERE EmployeeType IN ('C', 'T')
10. Seu aplicativo inclui um objeto SqlDataAdapter denominado sqlDataAdapter que
se conecta à tabela Employees. Com base neste SQLDataAdapter, seu aplicativo
também inclui um objeto DataSet dsEmployees. Qual a linha de código você deve
usar para carregar os dados do banco de dados no objeto DataSet?
a. dsEmployees = sqlDataAdapter.Fill("Employees");
b. sqlDataAdapter.Fill("dsEmployees", "Employees");
c. sqlDataAdapter.Fill(dsEmployees);
d. sqlDataAdapter.Fill(dsEmployees, "Employees");
176 | lição 6
■ Avaliação da competência
Cenário 6-1: criando um diagrama de relacionamento de entidades
Uma empresa tem um número de funcionários, e cada empregado pode ser atribuído a um
ou mais projetos. Além disso, cada projeto pode ter um ou mais empregados trabalhando
nele. Desenhe um diagrama de relacionamento de entidade para esta situação.
■ Avaliação de proficiência
Cenário 6-3: normalizando tabelas
Você está convertendo um diagrama de relacionamento de entidades em tabelas. Você
inventou o seguinte design de tabela:
Books
Você precisa aplicar as regras de normalização para garantir a integridade dos dados.
Como você poderá garantir que a tabela Books esteja na terceira forma normal?
177
Índice