Skip to content

Latest commit

 

History

History
1866 lines (1313 loc) · 44.6 KB

Caderno C#.md

File metadata and controls

1866 lines (1313 loc) · 44.6 KB

Bem vindo ao meu caderno

  • As coisas ficam mais legais a partir da aula 9

  • Veja os códigos das aulas na pasta CFB

    Otávio Dioscânio /2020

[TOC]

OS - Windows - Microsoff.Net - Framework64 - csc.exe

  • csc.exe é o compilador C#
  • pesquisar csc no prompt: mostra se está no path do sistema (provavelmente não vai estar). Logo, deve-se baixar o .Net SDK, o .Net Framework DevPack, o .Net Runtime
  • Programação orientada a objetos: todo programa me C# é uma classe
  • dir: revela o que está na pasta
  • apenas digitar o nome do arquivo para executá-lo
  • Compilar no prompt: csc Aula01.cs
  • Abrir uma pasta: cd Aula01
  • cls limpa o prompt

using System; class Exercicio1 { static void Main() { Console.WriteLine("Olá mundo!"); } }


Aula 2

Padrão dotnet: interface similar à JVM, para rodar em vários dispositivos Namespace organiza as classes


Aula 3 - Variáveis

  • int num; //deixa ele como 0

  • Declaração e atribuição

  • primitivas: int, char, float, byte float valor = 3.2f byte n1 = 10; // entre 0 e 255, não tem sinal. 8 bits

  • String não é primitiva

    var numero = 10; //quando não quiser especificar o tipo. É atribuído na compilação

    • Variáveis dentro de métodos podem ser declaradas como var em C# que o seu tipo é inferido automaticamente. Para o compilador acertar qual o tipo da variável ela deve ser inicializada no mesmo instante que é declarada e não pode ser atribuído o valor null.
    • Atenção: usar var não deixa de definir bem o tipo. Este não pode ser alterada à medida que o código é executado!

    int num1=0, num2=0;


Aula 4 - Escopo de variáveis

  • Onde ela é visível, pode ser utilizada

Aula 5 - Operadores

bool res = 10 < 5; // False

Incrementar

num = num + 1; num += 1; num *= 2; num++; // só funciona para somar 1``

& e |

bool res = (5 > 3) | (10 < 5);


Aula 6 - Formatando a saída no console

  • Lembrando que Console.WriteLine(); quebra linha.
  • Em vez de concatenar, utilizar índices a partir do 0.
  • \n quebra linha
  • \t insere um tab
  • Console.WriteLine("Val.Compra...:{0,15:c}", valorCompra);
  • c: valor monetário, p: porcentagem.

Aula 7 - Constantes

  • Uma vez atribuído um valor, ele não pode modificar (senão dá erro).
  • Tipo uma proteção para a variável.
  • Palavra reservada: const.
  • O restante é igual às variáveis.

const string canal = "CFB Cursos"; const double pi = 3.1415;


Aula 8 - Lendo valores no teclado

  • Console.Read() ou Console.ReadLine()
    • ReadLine quebra linha (ou adiciona uma?) depois do enter
  • Cuidado: tudo que é lido vai no formato String Duas formas de converter:

v1 = int.Parse(Console.ReadLine()); v2 = Convert.ToInt32(Console.ReadLine());


Aula 9 - Operações Bitwise

Bitwise para esquerda <<: dobra o valor da variável Os cinco últimos bits vão para a esquerda, completando um 0 no final ex.: 001010 = 10 010100 = 20 Para a direita >> : divide por 2 Elimina o último bit e desloca tudo para a direita 011010 = 26 001101 = 13

int num = 10;
num = num >> 1;	// desloca apenas 1 (divide apenas uma vez)
Console.WriteLine(num);	// 5 (para a direita divide)

di-di (direita divide)

int num = 10;
num = num << 2;
Console.WriteLine(num);	//40

cabo 11:49 23/09/2020


Aula 10 - Enumeradores (enum)

  • Criar um tipo personalizado com valores predefinidos
enum DiasSemana {Domingo, Segunda, Terça, Quarta, Quinta, Sexta, Sábado}
DiasSemana ds = DiasSemana.Domingo;	// DiasSemana é o tipo de ds
  • Converter o valor 3 no tipo DiasSemana
DiasSemana ds = (DiasSemana)3;	// uso de cast
Console.WriteLine(ds);	// Quarta
int ds = (int) DiasSemana.Sexta;
Console.WriteLine(ds);	// 5

Aula 11 - Conversão de tipo (typecast)

  • Quando a conversão não é implícita/segura

  • Não serve quando precisa de int.Parse ou Convert.ToInt32

  • Conversões implícitas: int -> float, int -> long

int n1 = 10;`
float n2 = n1;	// converte automaticamente
Console.WriteLine(n2);
float n2 = 10.5f;
int n1 = n2;	// float -> int não tem conversão implícita, mas existe a explícita
float n2 = 10.5f;
int n2 = (int) n1;	// typecast, explícita.

int vInt = 10;
short vShort = (short) vInt;	// cuidado
decimal numeroGrande = 10;
double numeroPequeno = 25;

numeroPequeno = (double) numeroGrande;
Console.WriteLine(numeroGrande + "  " + numeroPequeno);
short valorPequeno = 100;
long valorGrande = 25;

valorGrande = valorPequeno; // não precisa do cast pois long > short

Console.WriteLine(valorGrande);

Aula 12 - condicional if

Aula 13 - if, else if, else

  • lembrar que pode mudar a ordem e que não precisa de duas expressões no condicional

Aula 14 - if aninhados: if dentro de outro


Aula 15 - Switch case

  • Compara uma variável com seus cases
int tempo = 0;
char escolha;
escolha = char.Parse(Console.ReadLine());

switch (escolha) {
case 'a':
case 'A':	// testa os dois
    tempo = 50;
    break;	// faz parte da estrutura padrão do case
case 'c':
    tempo = 480;
    break;
case 'o':
    tempo = 660;
    break;
default:
    tempo =-1;
    break;
}

switch (variavelIndicada) {case}
  • Dúvidas: o default é obrigatório?

Aula 16 - Comando GoTo

  • Antigo, de uma época em que não existiam estruturas de repetição (programação em fluxo, e não estruturada que nem hoje).
  • Pode ser útil e tornar o código legível (ex.: loops profundamente aninhados)
  • Gera um desvio no programa para um ponto determinado
  • Cuidado, ele pode criar loops invisíveis
inicio:	// label
...
goto inicio;

while: if x >= 10 goto end
    print x
    x++
    goto while
end:

tryAgain:
    try {
        ...
    } catch (...) {
        goto tryAgain;
    }

return !(cond1 || cond2 || cond3);

Aula 17 - Arrays unidimensionais (vetores)

  • Coleção de variáveis do mesmo tipo
  • tipo, colchetes nome recebe new tipo [tamanho];
  • Mais fácil para criar, atribuir e ler variáveis
int[] meuArray = new int [5]; // 0-4

meuArray[0] = 111;
meuArray[1] = 200; meuArray[3] = 400; meuArray[4] = -20;

Console.WriteLine(meuArray[0]); // 111

string[] veiculos = new string[3];
  • Já atribuindo na declaração
int[] numeros = new int[3] {55, 77, 99};
Console.WriteLine(numeros[2]); // 99
  • Também dá:
int[] num = {55, 77, 99, 66, 88}; // não fica com tamanho limitado.
  • dúvida: não colocar o new tipo[tamanho] deixa o vetor dinâmico? Posso adicionar elementos após a criação?

Aula 18 - Arrays bidimensionais (matrizes)

  • Utiliza dois índices para localizar os elementos

  • É como se fosse uma tabela, índices de linha e coluna

  • No operador (colchetes) coloca-se uma vírgula

  • Os índices podem ter tamanhos diferentes

int [,] n = new int [3,5];	// linha, coluna

	/*
	10 20 30 40 50
	60 70 80 90 15
	25 35 45 55 65
	*/

n[0,0] = 10; n[0,1] = 20; n[0,2] = 30; n[0,3] = 40; n[0,4] = 50;
n[1,0] = 60; n[1,1] = 70; n[1,2] = 80; // ...
n[2,0] = 25; n[2,1] = 35; // ...

int [,] num = new int [2,2] {{10,20}, {30,40}}; // primira linha, segunda linha

Aula 19 - Loop FOR

for (int num = 0; num < 10; num + 1) {}

// declarar internamente: num só serve no escopo do for.
// enquanto a condição for verdadeira, ele vai executar
// obs.: ele começa e imprimir no 0 e vai até o 9, passando por 10 números
	
int[] num = new int[10];
for (int i = 0; i < num.Length; i++) {
	num[i] = i;
}
  • num.Length - tamanho do array (não é o último índice)
  • for é geralmente usado quando se tem certeza das vezes que o comando será repetido

Aula 20 - While

  • Inicialização e atribuição do contador antes do while
  • Operação de incremento dentro
int [] num = new int[10];
int i = 10;
while (i > 0) {
	Console.WriteLine(i);
	i--;
} // 10-1
  • Lembre-se que a última posição de um array é array.Length - 1

Aula 21 - Do While

  • Garante-se que, pelo menos uma vez, os comandos serão executados
do {
	Console.WriteLine(i);
	i++
} while (i < 5);

string senha = "123";
string senhauser;
int tentativas = 0;

do {
	Console.Clear();
	Console.WriteLine("Digite a senha");
	senhauser = Console.ReadLine();
	tentativas++
} while (senhauser != senha);

Console.WriteLine("Senha correta. Tentativas: {0}", tentativas);
  • obs.: Console.ReadKey();

Aula 22 - Loop FOREACH

  • Próprio para ler elementos de uma coleção
  • Cria uma variável que vai receber cada elemento da coleção (logo, precisa ser do mesmo tipo)
int [] num = new int[5]{11, 22, 33, 44, 55};

foreach(int n in num) {

	Console.WriteLine(n);	// coloca os valores no n. Não tem contador
	
}
  • Não é possível atribuir valor a n dentro do foreach (??)

Aula 23 - Métodos para arrays

  • Legenda: vetor = um array qualquer
Random aleatorio = new Randow();	// classe Random, objeto aleatorio

int valor = aleatorio.Next(50);
int valor1 = aleatorio.Next(-5, 250);
int tamanho = vetor.Length;
foreach (int elemento in vetor) { }
Array.BinarySearch (vetorPesquisa, valorProcurado);
  • retorna a posição. O array precisa estar ordenado (?). Caso não exista, retorna negativo.
Array.Copy(vetorOrigem, vetorDestino, quantidadeElementos);
  • quantidadeElementos conta a partir do 0?
vetorOrigem.CopyTo(vetorDestino, posicaoInicial);

vetor1.CopyTo(vetor3, 0);
vetor.GetLowerBound(dimensão);
vetor.GetUpperBound(dimensão);
  • retorna o menor/maior índice do vetor ou matriz (?)
vetor.GetValue(indice);
  • retorna object. indice é long. também serve para matriz
Array.IndexOf(vetor, valor);
  • posição da primeira ocorrência. -1 se não existir. somente para vetor unidimensional.
Array.Reverse(vetor);

vetor.SetValue(object valor, long indice);

Array.Sort(vetor);

Aula 24 - Métodos

  • Métodos são conjuntos de instruções, um bloco que pode ser invocado a qualquer momento;
  • Void: não retorna
  • É static pois o método principal também é
  • Os argumentos não precisam ser do mesmo tipo

Aula 25 - Passagem por valor e referência

  • Passagem por referência:
static void Main() {
    int num = 10;
    dobrar(ref num);	// ref na hora de passar
    Console.WriteLine(num); // 20
}
static void dobrar(ref int valor) { // ref no método
    valor *= 2;
}
  • A variável passada por parâmetro com ref entra no método, executa o código, e sai como se fosse global.
  • Cuidado: passagem por referência afeta variáveis, mesmo não havendo o return
  • valor aponta para o endereço de memória de num
  • Tem que usar o ref também na hora de chamar o procedimento e passar o parâmetro

Aula 25 - Argumento out

  • Possibilidade de o método ter mais de um valor de saída
static void Main() {
    int divid, divis, quoci, rest;
    dividendo = 10;
    divisor = 5;
    quoci = divide (divid, divis, out rest); // tem que usar o out aqui também
    Console.WriteLine(...) 
   
}

static int divide (int dividendo, int divisor, out int resto) {
    int quociente = dividendo / divisor;
    return quociente;
}

// return quociente, resto; -> não existe!!

out rest

out int resto

  • pelo visto você cria uma variável vazia que vai entrar no método só para receber um valor e voltar.

Aula 27 - Argumento params

  • Não precisa especificar o número de argumentos, pode ser 0 ou n.
  • Deve-se colocar uma forma de controle (ex.: if, else if) dentro do método
static void Main() {
    soma (10, 7, 8, 1, 4, 2);
    soma ();
    soma (1, 2);
}

// ---- jeito limitado (aceita até 2 parâmetros):

static void soma (int n1, int n2) {
    int res = n1 + n2;
    Console.WriteLine("A soma é " + res);
}

// --- com params - permite zero ou mais:

static void somaFlexivel (params int[] nomeArray) {
    int res = 0;
    if (nomeArray.Length < 1) {
        Console.WriteLine("Não existem valores para somar")
            
    } else if (nomeArray.Length < 2) {
        Console.WriteLine("Valores insuficientes");
        
    } else {
        for (int i = 0; i < nomeArray.Length; i ++) {
            res += nomeArray[i];
        }
        
    }
    
}

Aula 28 - Classes e Objetos

  • Classe: tipo de dado composto por membros (variáveis e métodos/funções da classe).

    • Onde vão ser instanciados os objetos. É a base, define o comportamento deles.

    • Objetos são independentes entre si, são instanciados em lugares diferentes da memória

[ModificadorClasse] class NomeDaClasse {
     // variáveis / propriedades
    [EspecificadorAcesso] tipo NomePropriedade;
    
    // métodos
    [EspecificadorAcesso] retorno NomeMetodo([arg1, ...]) {
        // corpo do método
    }
}
  • ModificadorClasse:

    • public: pública, sem restrição de visualização ou acesso em qualquer parte do programa. Não é o padrão se for omitido (e sim internal).

    • abstract: classe-base para outras classes, não pode gerar objetos.

    • sealed: selada, dela não pode haver herdeiros

    • static: não pode ser instanciada, mas é possível acessar seus membros, que também devem ser estáticos.

      • tudo que vai ser usado no construtor (Main) static deve ser static também.
  • EspecificadorAcesso:

    • public: sem restrição de acesso - qualquer membro, inclusive fora da classe, sem um método para isso. É o padrão.
    • private: só podem ser acessados pela própria classe. É o padrão.
    • protected: acessado na própria classe e nas classes derivadas (herança)
    • abstract: só há a implementação do cabeçalho do método, não a definição dele (que fica no bloco de código).
      • Obriga a implementação do método na classe que está herdando da classe pai
    • sealed: o método não pode ser redefinido
    • virtual: o método pode ser redefinido em uma classe derivada
    • static: o método pode ser chamado mesmo sem instanciar um objeto
      • pode usar o membro static sem precisar do New para instanciar
  • Futuramente: métodos construtores, destrutores

  • Boa prática: nome da classe com letra maiúscula.

  • Obs.: ainda não sei os defaults de class, main, variáveis

  • As classes e estruturas por padrão são internal, já os membros de classe/estrutura são privados por padrão.

    • Quando queremos trabalhar com bibliotecas externas ao projeto, nossas classes precisam ser declaradas com a visibilidade public

    • class Cliente { // internal class Cliente
      
      }

Variáveis que apontam para objetos

  • Uma vez que um objeto é criado, ele ganha uma posição estática na memória. Possui seus próprios atributos independentemente.

  • É possível que mais de uma variável aponte para o mesmo objeto e, caso haja modificação deste, será visível para todas as variáveis ao mesmo tempo

  • new: aloca a memória para um objeto e retornar o endereço dela

public class Jogador {
    public int energia = 100;
    public bool vivo = true;
}

public class Aula28 {
    
    static void Main() {
        
        Jogador j1 = new Jogador(); // criou o objeto j1 da classe Jogador
        Jogador j2 = new Jogador(); // instanciamento sem parâmetros
        Jogador j3 = new Jogador();
        
        j1.energia = 50;
        
        Console.WriteLine("Energia do jogador 1: {0}.", j1.energia);
        Console.WriteLine("Energia do jogador 2: {0}.", j2.energia);
        
       // 50, 100 (são independentes)                
    }
}
Conta mauricio = new Conta(); // mauricio aponta a um objeto
mauricio.Saldo = 2000;

Conta copia = mauricio; // copia passa a apontar para esse objeto (não cria outro)
copia.Saldo = 3000;

MessageBox.Show("Mauricio = " + mauricio.Saldo); // 3000
MessageBox.Show("Copia = " + copia.Saldo); // 3000

Aula 29 - Construtores e Destrutores

  • Método construtor: atua no objeto quando instanciado, tem a função de inicializar as propriedades/variáveis.
  • Toda classe tem um construtor, mesmo que não seja explícito
    • construtor padrão dentro da classe - não recebe argumentos e não executa nenhuma ação (tem o corpo vazio)
  • Basta que o método tenha o mesmo nome da classe
    • public+NomeDaClasse(){ }
public class Jogador {
    
    int energia; bool vivo;
    
    public Jogador() {	// método construtor
        
        energia = 100;
        vivo = true;
        
    }
}
  • É possível passar parâmetros para o Construtor da classe
public class Jogador {
    
    int energia; bool vivo;
    String nome;
    
    public Jogador(String n) {
        
        energia = 100; vivo = true;
        nome = n;
        
    }
}
  • Aí precisa colocar o nome ao instanciar:
Jogador j1 = new Jogador("Zenifreudo");	// ou zigofreudo
  • Método destrutor: chamado antes de o objeto ser destruído pelo garbage collector.
    • Não precisa definir visibilidade. Apenas um ~ seguido do nome da Classe.
		nome = n;	// continação, ainda dentro de classe
	}

	~Jogador() {	

		Console.WriteLine("Jogador foi destruído");

	}

Aula 30 - Sobrecarga de construtores

  • Permite mais um construtor para a classe.
  • Vários construtores de mesmo nome, mas o conjunto de parâmetros é diferente.
  • Obs.: sobrecarga de métodos é mesma coisa
public Jogador () { }
public Jogador (string n, int e) { }
	// etc

Jogador j1 = new Jogador();
Jogador j3 = new Jogador ("Théo", 50);
	// etc
  • No C#, ao invés de fazer sobrecarga de construtores, pode ser bom utilizar parâmetros opcionais com valores padrão.
  • Um construtor pode chamar outro: this(parametro)
Conta (String titular) {
	this.titular = titular;
}

Conta (int numero, String titular) {
	this(titular); // chama o construtor de cima
	this.numero = numero;
}

Aula 31 - Classes Estáticas

  • Não se pode instanciar a partir de uma classe declarada como static.
  • Logo, classes static não permitem o uso de construtores. O objeto static utiliza uma posição fixa na memória, não se usa new.
static public class Jogador {

	static public int energia;	// todos os membros são static também
	static public bool vivo;
	static public string nome;
    
	static public void iniciar (string n) {	// propriedades
        
		energia = 100;
		vivo = true;
		nome = n;
        
	}
	//...
}
  • Todos os membros (propriedades e métodos) são obrigatoriamente static também.
  • Classe disponível em todo o programa sem precisar instanciar um objeto.
class Aula31 {

static void Main () {
    
    	Jogador.iniciar("Otávio");	// acessa-se pela própria classe
		Jogador.info();
}
} 
  • A chamada é pela própria classe static, não há objetos (j1, j2, j3...)
  • Alterar uma propriedade da classe: surte efeitos em todo o sistema, pois o local da memória que todos acessam é fixo e comum.

Classe não static

  • Pode ter objetos.
  • Uma classe não static pode ter um membro static, mas não é obrigatório.
    • Neste caso, todos os objetos da classe vão apontar para a mesma propriedade, eles não terão uma própria.
    • Não é possível modificar individualmente.
  • Sem propriedade static:
class Inimigo {

	public bool alerta;	// não é static
	public string nome;

	public Inimigo(string n) {
		alerta = false;
		nome = n;
	}
    //...
}

class Aula31 {

static void Main () {
    Inimigo i1 = new Inimigo("Doido");
	Inimigo i2 = new Inimigo("Maluco");
    
    i1.alerta = true;	// funciona pois alerta não é static
    //...
}
  • Com alerta static:
class Inimigo {
    
	static public bool alerta;
    public string nome;
    
    //...
static void Main () {
    Inimigo i1 = new Inimigo("Doido");
	Inimigo i2 = new Inimigo("Maluco");
    
	Inimigo.alerta = true; // e não: i1.alerta = true;
    
	i1.nome = "oi"; // pode pois nome não é estático
}

Aula 32 - Operador This

  • Faz referência à propriedade da classe, e não do método. Ao objeto pai.
class Calculos {
	public int v1; // esse daqui é representado pelo this
	public int v2;
	
	public Calculos (int v1, int v2) {
		/*v1 = v1;
		v2 = v2;*/
     
		this.v1 = v1;
		this.v2 = v2;
    }

Aula 33 - Public vs Private

  • Propriedades private são inacessíveis fora da classe, tanto para escrita quanto para leitura.
  • Proteção aos membros: não dá para mudar/acessar sem um método público que permita.
    • define-se, inclusive, os valores aplicáveis à variável, se fosse public qualquer valor seria aceito.
    • filtro do valor a ser atribuído

Aula 34 - Herança

  • É um recurso da POO em que uma classe derivada (filha, subclasse) herda membros, propriedades e classes de uma classe base (pai, base)

  • Evidentemente, a classe derivada pode ter seus membros próprios

  • Importante: só herda o que for public

  • Uma classe derivada tem o nome da classe base depois de dois pontos

class Carro:Veiculo {
  • Pode ter espaço entre os dois
  • Caso queira modificar a regra de negócio de um método:
    • Colocar virtual no método da classe pai, dizendo que ele pode ser sobrescrito pela filha
    • Reescrever o método na filha com override antes

Aula 35 - Cadeira de herança e Construtor da classe base

  • O construtor da classe filha pode passar parâmetros para o construtor da classe base e executá-lo.
class Veiculo {						// classe base
	public Veiculo (int rodas) { 	// construtor
  • Construtor da classe derivada:
class Carro: Veiculo {				// classe derivada
    //...
	public Carro(string nome, string cor):base(4) {
  • base() é palavra reservada que, neste caso, se refere ao construtor da classe pai
Cadeia de herança
  • Imagine uma outra classe que herda Carro (que já herda Veículo)
class CarroCombate:Carro {
	public int municao;
    
    public CarroCombate():base("Carro de batalha", "verde") {
		municao = 100;
		ligar();
		setRodas(6);
    }
}
  • Na hora de instanciar:
CarroCombate cc1 = new CarroCombate();
Operador ternário
return (ligado ? "sim" : "não");

([expressão] ? [valor1] : ([expressão] ? [valor1] : ([expressão] ? [valor1] : [valor2])))
  • Não pode ficar sem o else, nem colocar null no lugar dele.

Aula 36 - Membros Protected

  • Atributos privados só são visíveis para a classe que os declarou. Os filhos não enxergam.

  • Atributos/métodos marcados como protected são visíveis apenas para a própria classe e para as classes filhas.

  • No exemplo anterior Veiculo não conseguiria acessar propriedades ou atributos private.


Aula 37 - Herança: ordem de execução dos construtores

  • Ao instanciar um objeto de Derivada2, todos os construtores serão executados.
  • A ordem de execução de construtores é sempre da base para a derivada.
  • No código, base -> derivada1 -> derivada2

Aula 38 - Métodos Virtuais

  • São métodos que têm o mesmo nome mas estão em classes diferentes, sendo que uma herda a outra

  • Executam uma ação diferente

  • Virtual: será sobrescrito em uma classe derivada

  • Override: vai sobrescrever em uma classe derivada

virtual public void info() { // quem é virtual pode ser sobrescrito. Está na classe pai

}
// ...

override public void info() { // sobrescreve. Está na classe filha

}
// ...

override public void info() { // classe mais específica, sobrescreve 

}

deriv2.info();
  • Não precisa codificar o método virtual, já que ele não será executado, deixe o espaço entre chaves vazio (não precisa de definições, só da assinatura)
  • Percebi que usar as palavras virtual ou override só evitar warnings, mas o código compila sem elas.

Base

  • É possível reutilizar o comportamento do método da classe pai, usando a palavra base
public class ContaPoupanca : Conta
{
	public override void Saca(double valor)
	{
		base.Saca(valor + 0.10);
	}
}

Ref

Base Ref;
Ref = deriv2;
Ref.info();	// "Derivada2"
  • Ref tem que ser com letra maiúscula, é palavra reservada.

  • Elemento de referência que pode receber as classes derivadas dessa base


Aula 39 - Classes e métodos abstratos

  • Classe abstrata: classe de referência/base para outras classes que vão herdar dela.
    • Não dá para instanciar objetos!
    • Não pode ser sealed ou abstract
  • Em métodos abstratos, não se implementa o comportamento, cria-se apenas o protótipo que vai servir como guia para as classes herdeiras. Não há conteúdo.
    • Obriga que as classes derivadas implementem os métodos
  • Métodos não abstratos: contêm a implementação, que é obrigatória.
  • Esqueceu? [Veja aqui](#Tipos Classe)
abstract public void aumentarPeso(int peso); // é obrigatório que seja sobrescrito
override public void aumentarPeso(int peso){
    this.peso += peso;
}
  • Resumo: é um guia, obriga implementação, não tem código. Usar ponto e vírgula.
  • Uma classe abstrata pode não ter um método abstrato, mas todo método abstrato precisa estar em uma classe abstrata

Aula 40 - Classes Sealed

  • Classe selada: não pode ser herdada.
sealed class Comida {
  • Dá para instanciar objetos normalmente, só não pode usá-la como base.

Aula 41 - Acessors GET e SET - encapsulamento

  • É possível ler, atribuir ou calcular pela propriedade Acessor
  • Nunca devemos expor os atributos da classe utilizando o public.
    • Inclusive usar os Acessors facilita a manutenção do código, caso sejam alteradas as regras de negócio.
    • Deixar o set privado é importante também, pois de nada vale deixar outras classes modificarem o atributo pela propriedade - o encapsulamento seria inútil.
  • Não é obrigatório implementar um get (read) e um set (write) juntos. Inclusive eles podem ser privados
  • value é o valor atribuído à propriedade.
public int Peso {	// não possui parâmetros
    
	get {
		return peso;
	}
    
	private set {			// não confundir Peso com peso!
		if (value < 0) 
            peso = 0;
		else if (value > 200) 
            peso = 200;
		else 
            peso = value;
        
	}  				// set não tem return
}
bicho.Peso = 140;	// usa o acessor set
Console.WriteLine("Peso: " + bicho.Peso); // usa o get
  • Auto-implemented properties - a partir do C# 3.0
    • ao utilizarmos as auto-implemented properties, só podemos acessar o valor do atributo declarado através da propriedade (mesmo que seja de dentro da classe).
class Conta
{
	public int Numero { get; set; }
}

Aula 42 - Indexadores de Classes

  • Membro de uma classe que permite que os objetos dela possam ser indexados como arrays.
  • Aplicação (ex.): valores diferentes em situações diferentes
  • Obs.: this é o que indexa
  • Dúvidas: 1) onde está a referência no cabeçalho do indexador de que é o peso a ser indexado e acessado pelos objetos? 2) só pode um indexador por classe? poderia ter bicho.peso[1] e bicho.altura[2]?
private int[] peso = new int[5]{80, 120, 160, 240, 300};
public int this[int i] { // indexador 
		
	get {
		return peso[i];
	}

	set {	
		if (value < 0)
			peso[i] = 0;
		else if (value > 200)
			peso[i] = 200;
		else 
            peso[i] = value;
	}
}
Console.WriteLine("Peso: " + bicho[2]);
bicho[2] = 140;
Console.WriteLine("Peso: " + bicho[2]);

Aula 43 - Interfaces

  • Interfaces só possuem as assinaturas dos métodos. Não possuem propriedades, não dá para declarar ou atribuir variável, não pode ter construtor ou destrutor, não define membros static ou método operator. Muito parecido com classe [static](#Tipos Classe).
public interface Veiculo {
  • Toda classe que usar uma interface precisa obrigatoriamente implementar seus métodos.
  • Uma classe pode herdar múltiplas interfaces
class Carro:Veiculo, Combate{
  • Se definir a herança mas não implementar: dá erro.

error CS0535: 'Carro' não implementa o membro de interface 'Veiculo.ligar()'

  • Pode ser implementado e não executar nenhum comando
public void info() {}
  • Utilidade (exemplo): somente algumas herdeiras de uma classe vão ter determinado método da classe pai. Como não dá para usar polimorfismo (pois se aplica a todas as filhas) .... CONTINUE
  • Métodos declarados dentro de uma interface nunca têm implementação e sempre são públicos.

Aula 44 - Struct

  • Estrutura é um tipo especial que permite o armazenamento de diferentes tipos de dados. É mais simples e se parece com classe.
  • Como não é classe, não pode herdar nem servir como base
    • Mas pode ter construtores
    • Construtor vai ser chamado desde que o operador new seja usado na instanciação do objeto (como já sabemos)
  • Tipo valor, e não referência
struct Carro {
Carro c1;				// sem chamar o construtor
c1.marca = "Nissan"		// nesse caso marca é public
Carro c2 = new Carro("Nissan ", "Versa rebaixado ", "Azul ");
// chamando o construtor

Aula 45 - Array de Struct

  • Quando quer criar vários objetos de um mesmo tipo (Struct é um tipo)
  • Isso não serve para classes.
Carro [] concessionaria = new Carro[4];
concessionaria[0].marca = "HRV";
concessionaria[0].cor = "Prata";

Aula 46 - Métodos que retornam objetos

voltar nessa aula, entendi pouca coisa 😢

	return new Ovo(numOvo, nomeGalinha); // chama o construtor

Aula 47 - Sobrecarga de métodos

  • Os métodos devem ter parâmetros diferentes (em número ou tipo).
  • Funções de mesmo nome que fazem coisas diversas.
public double soma(params double[]n) {
		double soma = 0;
		foreach (double i in n) {
			soma += i;
		}
		return soma
}

public int soma(params int[]n) {
		int soma = 0;
		for (int i = 0; i < n.Length; i++) {
			soma += n[i];
		}
		return soma;
}

Aula 48 - Recursividade

  • Função recursiva: que chama ela mesma. Precisa-se de uma condição de parada.
  • Fatorial e somatório: exemplos clássicos
  • Substitui estruturas de repetição.
public int fat(int n) {
	int res;
	if (n <= 1) {
		res = 1;  // controle de parada
	} else {
		res = n * fat(n - 1); // modificação de n
	}
	return res;
}

Aula 49 - Métodos e Variáveis Estáticos (static)

  • Não estão necessariamente em uma classe static
  • Acessar os métodos da classe sem precisar declarar um objeto.
  • Podem ser chamado de qualquer lugar (se forem públicos)
class Mat {

	public static double pi = 3.14;

	public static int dobro (int n) {
		return n * 2;
	}
}
class Aula49 {
	static void Main() {
		double vPi = Mat.pi;	// propriedade
        int vinte = Mat.dobro(10); // função
    }
}

Aula 50 - Delegates

  • É um objeto que faz referência a métodos
  • Ex.: uma classe com vários métodos static e um delegate que faz referência a eles.
  • delegate possui o endereço de entrada do método, não a rotina inteira
  • desafio: fazer o mesmo programa com params
using System;

delegate int Op(int num1, int num2);

class Matematica {

	public static int soma(int n1, int n2) {
		return n1 + n2;
	}

	public int multi(int n1, int n2) {
		return n1 * n2;
	}
}
class Aula50 {
	static void Main() {
		int res;
		Op d1 = new Op(Matematica.soma);
		res = d1(3, 4);       
    }
}
  • O que eu entendi: cria-se um objeto da "classe" delegate; ele recebe o método pelo parâmetro do construtor, comportando-se como o próprio método. (não entendi a utilidade).

Aula 51 - Argumentos de entrada do programa

  • Usa-se um array, que pode ter qualquer nome;
static void Main(string[] args) { // array
	if (args.Length > 0) {
			Console.WriteLine("Quantidade de argumentos: " + args.Length);
		// ...
  • Passando os parâmetros na hora de executar:

.\Aula051-ArgumentosEntrada oi ola sim verdade

Quantidade de argumentos: 4 oi na posição 0 ola na posição 1

//...

  • Pergunta: tem que ser string? tem que ser vetor?
    • Consegui compilar com int e double, mas deu um warning. Só foi possível passar número inteiro como argumento (nesses dois casos).
    • tem que ser vetor, tentei Main(string a, string b) e deu erro.

Aula 52 - Exceções (parte 1) - Try Catch

  • Exceções = erros

  • Toda exceção é representada por uma classe que herda da classe Exception

  • Em uma zona crítica, é possível definir o caminho caso dê erro (tratamento de erro)

Exceção Sem Tratamento: System.DivideByZeroException: Tentativa de divisão por zero. em Aula52.Main()

  • Quando dá problema: executa o que está no catch e continua a execução normal do programa.
    • A continuação se dá a partir do catch. Atenção: se ocorrer um erro na primeira linha do try, as demais linhas dele não serão executadas, pois o desvio é imediato.
n1 = 10;
n2 = 0;
		
try {
	res = n1 / n2;
    Console.WriteLine("Não deu erro na linha anterior. Ufa!");
} catch {
	Console.WriteLine("ERRO!");
}

ERRO! 10 / 0 = 0

  • Gerar mensagem:
    • Recebe objeto da classe Exception
/...
} catch (Exception e) { // ou mais específico: DivideByZeroException e
	Console.WriteLine("ERRO! " + e.Message);
    Console.WriteLine(e);
    Console.Writeline(e.GetType)
}

Aula 53 - Tratamento de Erros (parte 2) - Try Catch Finally

  • bloco finally: é executado independentemente do disparo da exceção
try {
	// executado até a linha do erro
} catch {
	// só quando dá erro
} finally {
	// executado sempre
}
  • E se eu quiser fazer minha própria exceção? Dá para forçar/criar um erro:

throw new Exception(string message);

try {
	res = n1 / n2; // aqui não deu erro
	Console.WriteLine("{0} / {1} = {2}", n1, n2, res);
    
	throw new Exception ("Encontrei um erro!"); // entra no e.Message 

} catch (Exception e) {	
//...
  • Veja no código da aula a mensagem criada em um método de uma classe.
  • throw new Exception("Mensagem") pode estar em qualquer lugar do código

Aula 54 - Namespaces

  • Controle de escopo.
  • Pode-se classificar os elementos dentro do Namespace. Agrupamento de classes por tipo.
  • É possível ter duas classes ou funções de mesmo nome mas em namespaces diferentes.
    • o local/escopo é diferente
    • Na hora de chamar deve-se indicar o namespace
  • System.Console.WriteLine();
  • Boa prática: todas as classes devem ser definidas em um namespace
  • Diretiva using: traz todas as classes de um namespace para o escopo do projeto
    • Não é preciso qualificar explicitamente
  • Assembly/montagem: classes compiladas em Assemblies - arquivos usualmente com a extensão .dll
    • Uma montagem pode conter classes definidas em muitos namespaces, e um namespace pode ocupar vários assemblies
    • Para usarmos as classes de um assembly, precisamos adicionar uma referência no projeto, e incluir a diretiva using adequada
  • Referência: permite que utilizamos tipos disponíveis em outros Assemblies
namespace Calc1 {
	class Area{
	}
}
namespace Calc2 {
	class Area {
	}
}
class Aula54 {
	static void Main() {
		area = Calc1.Area.Quad(0, 5F); // teve que indicar o namespace
	}
}

Aula 55 - Coleção Dictionary

  • Coleção de dados que são relacionados pelas chaves

  • Quantidade de itens específica/genérica

  • Tem que importar a biblioteca System.Collections.Generic

using System;
using System.Collections.Generic;
  • Construtor genérico:
Dictionary <tipoChave, tipoDado> nome = new Dictionary <tipoChave, tipoDado> ();
Dictionary <int, string> veiculos = new Dictionary <int, string> ();
  • Adicionar elementos
nomeDicionario.Add(chave, valor);
veiculos.Add(5, "Aviao");
  • Propriedade count (não é método)
veiculos.Count; // tipo int
  • Método clear
veiculos.Clear(); // limpa tudo
  • Verificar se determinada chave ("posição") está preenchida: dictionary.ContainsKey(key)
    • Lembrar que o preenchimento do dicionário não precisa ser sequencial. Usar as chaves 10, 32 e 150 não vincula os valores ignorados. Lembrar que é um índice, não precisa ser numérico, isso aqui não é array.
if (veiculos.ContainsKey(20)){ // retorna booleano (e não o valor)
  • Se existe um valor na coleção: dictionary.ContainsValue(value)
if (veiculos.ContainsValue("Navio")) { // retorna booleano (e não a chave)
  • Remover um valor específico: método dictionary.remove(chave)
veiculos.Remove(20);
  • Propriedades Keys e Values retornam coleções com chaves e valores, respectivamente. Precisa de um elemento Keycollection
  • Substituir um valor (também me parece um substituto de dicionario.Add(chave, valor);
dicionario[chave] = valor;
veiculos[15] = "Bicicleta";
  • For ou foreach para imprimir todos os elementos de uma coleção
foreach (string v in veiculos) { // não rola pois string não é o tipo da coleção
	Console.WriteLine(v);
}

foreach (KeyValuePair<int, string> v in veiculos) {
    Console.WriteLine(v.Value);	// ainda precisa indicar se quer a chave ou o valor.
}

foreach (string v in veiculos.Values) { // o mais fácil
    Console.WriteLine(v);
}
  • Outra forma de imprimir
    • Todos os elementos estão no valores, que é do tipo ValueCollection
Dictionary <int, String>.ValueCollection valores = veiculos.Values;

foreach string v in valores {
    Console.WriteLine(v);
}
  • Observação: às vezes usa-se Key/Value no plural, às vezes no singular. Observe o contexto: refere-se a somente um valor específico ou a todos do dicionário?

Aula 56 - Coleção LinkedList = Lista duplamente encadeada

  • Cada elemento é um nó da lista, que tem os links para os elementos posterior e anterior
  • Vou chamar de lista2 para não confundir com List (próxima aula)
  • Lembrar do using System.Collections.Generic;
LinkedList<tipoLista2> nomeLista2 = new LinkedList<tipoLista>();
LinkedList<string> transporte = new LinkedList<string>();
  • lista2.AddFirst(valor);
    • Adiciona o valor no início. Ou seja, o último a ser adicionado é o primeiro a ser impresso.
  • lista2.AddLast(valor);
    • Adiciona no final;
transporte.AddFirst("Carro");
transporte.AddLast("Aviao");

06:50 12/10/2020

  • lista2.AddAfter(node, value), lista.AddBefore(node, value);
LinkedListNode<string> no;
no = transporte.FindLast("Navio"); // .FindLast(valor) renorna um nó de lista encadeada
transporte.AddAfter(no, "Charrete");
transporte.AddBefore(no, "Patinete");
  • node.Next; node.Previous; node.Value
no = transporte.FindLast("Motocicleta").Next; // no = valor seguinte à motocicleta

Console.WriteLine(no.Value);
Console.WriteLine(no.Previous.Value); // "Motocicleta"
  • lista2.Remove(value), RemoveFirst(), RemoveLast(), Clear()
lista2.Remove(valor); // valor específico

lista2.RemoveFirst(); // primeiro
lista2.RemoveLast(); // último

lista2.Clear(); // apaga tudo
  • Imprimir os elementos (mais fácil que dicionário)
foreach (string v in transporte) {
	Console.WriteLine(v);
}
  • lista2.Find(value)
    • Retorna a referência se existir ou null se não existir;
if (transporte.Find("Carro") == null) {
	Console.WriteLine("Não encontrado");
} else {	
	Console.WriteLine("Elemento encontrado");
}

Aula 57 - Coleção List (Parte 1)

  • Eu chamei o LinkedList anterior de lista, mas entenda que ele é diferente de List
  • Usada para substituir o array tradicinal. Mais versátil, mais fácil de trabalhar. Possui vários métodos. "Array tunado"
  • Não esquecer do using System.Collections.Generic;
List<string>carros = new List<string>();	
  • lista.Add(valor)
    • obs.: testar se o add funciona com LinkedList
veiculos.Add("HRV");
  • lista_recebe.AddRange(lista_envia);
veiculos.AddRange(carros); // copia todos os elementos da lista carros para veiculos
  • lista.Clear();
  • lista.Contains(valor);
    • retorna true ou false
if (carros.Contains(valor)) {
  • lista_envia.CopyTo(array_destino, pos_array_destino);
    • O destino não pode ser outra lista (pelo menos foi o que eu percebi), e sim um array.
    • CopyTo copia todos os elementos da lista para o array, a partir da posição indicada deste.
string [] carros2 = new string[10];
carros.CopyTo(carros2, 2); // pos 0 e 1 ficarão com seus valores de antes
  • lista.IndexOf(valor);
    • retorna a posição da primeira ocorrência ou -1 (se não encontrar)
Console.WriteLine("Está na posição " + carros.IndexOf(valor));
  • Impressão dos itens é igual LinkedList
foreach (string x in carros) {
	Console.WriteLine(x);
}

Aula 58 - List (Parte 2)

  • lista.Insert(pos, valor);
carros.Insert(1, "Cruze");
  • lista.LastIndexOf(valor);
carros.Add("HRV");
int ultimo = carros.LastIndexOf("HRV");
  • lista.Remove(valor); e lista.RemoveAt(posicao);
carros.Remove("Argo");
carros.RemoveAt(0);
  • lista.Reverse();
carros.Reverse(); // simplesmente inverte
  • lista.Sort();
    • Ordem alfabética ou numérica
carros.Sort();
  • lista.Count; // se não tiver elementos, o resultado é zero
int tamanho = carros.Count // propriedade. É tipo um length
  • lista.Capacity;
    • Quantos elementos cabem na lista. Dá para alterar
    • É uma propriedade também
    • Diminuir a capacidade para um número menor do que Count dá erro
int cap = carros.Capacity;
carros.Capacity = 15;

Aula 59 - Coleção Queue (Fila)

  • Última aula no modo console, na próxima teremos VS 2019 com janela gráfica 🎉
  • Particularidade: o primeiro a ser adicionado é o primeiro a sair. First In, First Out.
  • Só dá para visualizar o elemento que está na frente (em primeiro), não é possível manipular os demais
Queue<string>veiculos = new Queue<string>();
  • Dá para inicializar passando uma coleção para o construtor (tem que testar se isso funciona para as outras coleções)
string[] vs = {"Carro", "Moto", "Navio", "Aviao"};
Queue<string> veiculos = new Queue<string>(vs);
  • fila.Enqueue(valor); // adicionar elementos no final da fila
veiculos.Enqueue("Jegue");
  • fila.Count; // quantos espaços estão preenchidos

  • fila.Contains(valor); // retorna true ou false

    if (comidas.Contains("Bolo")) {
  • fila.Clear();

  • fila.Dequeue(); // retornar e remover elementos do início da fila

    • Retorna o primeiro elemento da fila e o remove dela
Console.WriteLine("Primeiro veículo: " + veiculos.Dequeue()); // 
Console.WriteLine(veiculos.Count); // terá um elemento a menos
  • fila.Peek(); // apenas retornar o primeiro
    • Retorna o primeiro elemento mas não remove.
Console.WriteLine("Primeiro: " + veiculos.Peek());
  • Imprimir todos os elementos
    • pode fazer com foreach + peek/dequeue ou um foreach normal (abaixo)
foreach (string z in veiculos) {
	Console.WriteLine(z);
}
  • Mas atenção: Queue não trabalha com indexadores. Não existe: int c = veiculos[3]
    • Só consegue acessar o primeiro elemento da fila.
while (veiculos.Count > 0) {
	Console.WriteLine(veiculos.Dequeue);
}
Console.WriteLine(veiculos.Count); // 0
  • Ex. de uso: um jogo de cartas em que se retira cartas de um monte.

Até mais ✔

  • Termina aqui o modo console
  • Estes foram os pontos principais da linguagem C#. Não é tudo que o que a linguagem faz, faltou muita coisa!

12/10/2020, segunda