De forma geral, se você analisar linguagens como C, C++ e C#, vai perceber uma diferença fundamental:
- Um programa em C é um conjunto de funções e tipos de dados
- Um programa em C++ é um conjunto de funções e classes
- Já a essência de um programa C# é formada por um conjunto de declarações de tipos
O código-fonte de um executável C# (arquivo EXE) ou biblioteca de ligação dinâmica (DLL) é composto por uma ou mais declarações de tipos.
Arquivos DLL não possuem ponto de entrada Main; por outro lado, um executável (EXE) precisa declarar pelo menos uma classe com um método chamado Main, que serve como ponto de início do programa.
Softwares grandes contam com milhares de tipos (classes e outros) no código-fonte. Projetos amplos são desenvolvidos por vários programadores, cada um responsável por módulos separados, o que torna inevitável conflitos de nomes iguais entre tipos. Como evitar esses conflitos? É aí que entram os «namespaces» (espaços de nomes) que citamos anteriormente.
O namespace (espaço de nomes) tem como função agrupar declarações de tipos relacionadas e atribuir um nome único a esse grupo. Como todo programa é basicamente uma coleção de tipos interligados, os desenvolvedores geralmente criam namespaces personalizados para guardar todos os tipos do projeto.
Simplificando, um espaço de nomes adiciona um rótulo de grupo a um conjunto de classes. Qualquer trecho de código fora desse grupo precisa informar esse rótulo para acessar as classes em questão.
Imagine uma turma com dois alunos de nome idêntico. Professores e colegas não conseguem diferenciá-los apenas pelo nome, então adicionam uma marca de grupo: por exemplo, TOM do Grupo A e TOM do Grupo B. As marcações A e B exercem exatamente a mesma função dos espaços de nomes.
O código abaixo exemplifica um programa com três declarações de tipos, todos definidos dentro de um namespace chamado MyProgram.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace HelloDemo // Declarar um namespace
{
class A // Declarar o tipo A (classe)
{
void Fun1() // Função
{
// Lógica do programa
}
}
class B // Declarar o tipo B (classe)
{
void Fun1() // Função
{
// Lógica do programa
}
}
class C // Declarar o tipo C (classe)
{
static void Main(string[] args) // Ponto de entrada Main do programa
{
double pi = 3.14;
string webSite = "foxdevelop.com";
Console.WriteLine($"The Pi is {pi} and the website is {webSite}.");
}
}
}
Code language: PHP (php)
Vamos estudar os namespaces de forma detalhada nas próximas aulas.
O tipo é um modelo
Como um programa C# nada mais é que uma coleção de declarações de tipos, dominar a linguagem significa aprender a criar e utilizar tipos. Primeiro, é preciso entender:
O que é um Tipo (Type)
Você pode interpretar um tipo como um modelo para criar estruturas de dados: ele não é uma estrutura de dados concreta por si só, mas define todas as características que os objetos gerados desse modelo terão.
Um tipo é apenas um «projeto», ele não ocupa memória sozinho; a alocação de memória e armazenamento de dados só ocorrem na instanciação.
O tipo é um projeto usado para gerar objetos concretos. Compara-se ao desenho de uma casa: com um único desenho, é possível construir várias residências distintas.
Cada tipo é definido por três componentes:
- Nome
- Estrutura para armazenar os dados dos membros
- Comportamentos e restrições
Em C#, tudo é um tipo, inclusive os tipos primitivos nativos.
Abaixo dois exemplos de tipos nativos: short e int.
Sua estrutura segue o formato abaixo:
| Tipo short | Tipo int |
|---|---|
| Nome: short | Nome: int |
| Estrutura: ocupa 2 bytes | Estrutura: ocupa 4 bytes |
| Comportamento: inteiro de 16 bits | Comportamento: inteiro de 32 bits |
- Nome: identificador do tipo (
int/string/nomes de classes customizadas) - Estrutura de armazenamento: define o tamanho de memória e disposição dos campos (ex:
shortocupa sempre 2 bytes) - Restrições de comportamento: estabelece operações suportadas, faixa de valores e métodos nativos (ex:
intaceita operações aritméticas, faixa de valores-2^31 ~ 2^31-1)
Instanciação (Instantiate)
Criar um objeto de dados funcional a partir do modelo de tipo com a palavra-chave new
Objeto (object) = Instância (instance)
Usando os tipos int e short citados antes, podemos criar instâncias. No código abaixo, pi, age e nums são instâncias criadas respectivamente dos tipos double, int e short.
namespace HelloDemo
{
class Program
{
static void Main(string[] args)
{
double pi = 3.14;
int age = 12;
short nums = 23;
}
}
}Code language: JavaScript (javascript)
Em C#, todas as variáveis e dados do programa são, sem exceção, instâncias de algum tipo; não existem dados sem tipo definido.
Consulte o exemplo de código anterior
A classe C do exemplo é a classe de ponto de entrada e satisfaz todos os requisitos de um arquivo executável:
- É um tipo customizado contido no namespace
MyProgram - Possui o método estático sem retorno
Main, que funciona como ponto de inicialização do aplicativo
C# não tem apenas o tipo class
Todos os tipos declaráveis em C#: Classe (class), Estrutura (struct), Interface (interface), Enumeração (enum), Delegado (delegate), Registro (record)
BCL (Base Class Library): Biblioteca de classes padrão nativa do .NET, que disponibiliza tipos predefinidos do sistema como int, short, string, List<T>, os quais o desenvolvedor pode instanciar e usar diretamente.
Declaração de tipo