Menu

Conhecendo Arrays em C#

O array é um tipo de referência, não é um tipo de valor!

Quando tenho variáveis que compartilham o mesmo contexto, posso "juntar" todas num tipo chamado array! Um array agrupará vários tipos da mesma variável sendo possível consultar por índices. Por exemplo: 

Tenho um conjunto de peças, e quero guardar quantas peças iguais tenho em cada conjunto. Supondo que seria uma coleção de números inteiros: 

int conjunto_1 = 15;
int conjunto_2 = 20;
int conjunto_3 = 13;
int conjunto_4 = 22;

Para representar todos os conjuntos agrupados, sem ter que declarar uma variavel para cada um, podemos usar um conjunto de números interios, representado por um array, dessa forma:

int[] conjunto;

Para inicializar essa nova variavel que declaramos, que é do tipo array, precisamos informar ao compilador que estamos criando uma váriável que suporta diversos valores do tipo inteiro. Não basta simplesmente atribuir um valor inteiro, pois não é mais um valor inteior único... é um conjunto de valores inteiros.

O compilador também precisa saber quantos valores iremos armarezar na memória, qual a quantidade de espaço ele precisará cirar, e para isso, informamos também esse valor!

int[] conjunto = new int[4];
conjunto[0] = 15;
conjunto[1] = 20;
conjunto[2] = 13;
conjunto[3] = 22;

Dessa forma, criamos um array de inteiros com 4 posições (lembrando que o índice inicial aqui sempre será zero). Mas o que acontece se você inicilizar um array de 4 posições e não colocar nenhum valor nessa última posição? O valor padrão de inicialização é 0! Agora, como iterar sobre esse array? Fácil! Podemos acessar algumas propriedade especificas do array:
for(int indice = 0; indice < conjunto.Length; indice++){
	Console.WriteLine($"Acessando o array no índice: {indice}, com valor: conjunto[{indice}]");
}

Entendendo Herança e Interface em C#

Começando pela Herança:
Herança é um princípio de orientação a objetos, que permite que classes compartilhem atributos e métodos, através de "heranças". Ela é usada na intenção de reaproveitar código ou comportamento generalizado ou especializar operações ou atributos
Dessa forma, podemos criar uma situação hipotética para exemplificar uma herança. Supondo que temos um sistema de uma empresa. Nesta empresa teremos funcionários... então vamos criar a classe funcionario:
public class Funcionario
{
	public string Nome { get; set; }
	public string CPF { get; set; }
	public double Salario { get; set; }
}
Mas os funcionários podem ter características específicas, tais como Diretor, Desenvolvedor, Vendedor, etc... Normalmente, poderíamos criar para cada um outra classe:
public class Diretor
{
	public string Nome { get; set; }
	public string CPF { get; set; }
	public double Salario { get; set; }
}
mas neste caso estaríamos apenas repetindo código. Funcionário tem as mesmas propriedades do Diretor... e do Desenvovledor também terá. Para evitar repetição de código e relacionar dizer pro compilador que toda classe de Diretor é um Funcionário, podemos utilizar o conceito de Herança. No C# para especificar a herança usamos dois pontos, assim:
public class Diretor : Funcionario { }
Através desse código, podemos criar um objeto Diretor e estanciar as mesmas propriedades de um funcionário:
Diretor camila = new Diretor();
camila.Nome = "Camila";
camila.CPF = "123.456.789-01";
camila.Salario = 1000;
E os métodos? Também são compartilhados? Sim! Por exemplo:
public class Funcionario
{
	public string Nome { get; set; }
	public string CPF { get; set; }
	public double Salario { get; set; }
    
	public void AumentarSalario()
	{
		Salario *= 1.15; //aumento de 15%
	}
}

public class Diretor : Funcionario
{
	public void AumentarSalario()
	{
		Salario *= 1.11; //aumento de 11%
	}
}
Supondo que o aumento do Diretor é diferente de um funcionário comum, poderíamos criar este código, porém a função AumentarSalario() não será sobrescrita se tivermos o seguinte código:
Funcionario funcionario = new Diretor();
Mesmo sendo completamente compilável e correto, a função AumentarSalario não estará correta. Para sobrescrever funções, em caso de herança em C#, é necessário tornar a função da classe mais genérica virtual. Dessa forma sinalizamos para o compilador que ela pode ser sobrescrita por outras classes... e na classe que herda temos que especificar que a função será sobrescrita. Para isso usamos as palavras reservadas "virtual" e "override".
public class Funcionario
{
	(...)
	public virtual void AumentarSalario()
	{
		Salario *= 1.15; //aumento de 15%
	}
}

public class Diretor : Funcionario
{
	public override void AumentarSalario()
	{
		Salario *= 1.11; //aumento de 11%
	}
}
Dessa forma garantimos que o código sempre retorne a porcentagem correta de aumento para o Diretor. Mas, todo funcionário sempre terá um tipo específico, não é mesmo? Então instanciar a classe funcionário pode gerar um problema, pois não saberemos qual funcionário se trata. Gostaríamos de sempre instaciar apenas as classes que herdam de funcionário. Em C#, para impedir que isso aconteça, tornamos a classe abstrata.
Classes abstratas são classes que servem como modelo para suas subclasses. Classes abstratas não podem ser instanciadas, apenas herdadas. Os métodos declarados na classe abstrata devem ser implementados nas subclasses (classes concretas).
Assim, impedimos que classes genéricas sejam instânciadas. Porém, quando uma classe se torna abstrata, como vimos na descrição, ela não deve implementar métodos, apenas indicar métodos que devem ser implementados nas classes que herdam dela, dessa forma, o nosso novo código será:
public abstract class Funcionario
{
	(...)
	public abstract void AumentarSalario();
}

public class Diretor : Funcionario
{
	public override void AumentarSalario()
	{
		Salario *= 1.11; //aumento de 11%
	}
}
Existe também a possibilidade, no C#, do uso da palavra reservada "base" quando desejamos passar informações da subclasse para a classe abstrata. Podemos utilizar o exemplo no caso de termos construtores:
public abstract class Funcionario
{
	(...)
	public Funcionario(string cpf, double salario)
	{
		CPF = cpf;
		Salario = salario;
	}	
	public abstract void AumentarSalario();
}

public class Diretor : Funcionario
{
	public Diretor(string cpf) : base(cpf, 5000)
	{ }
        
	public override void AumentarSalario()
	{
		Salario *= 1.11; //aumento de 11%
	}
}
No código acima, definimos que toda vez que instaciamos uma classe que herda de Funcionario deve ser especificado, obrigatoriamente um CPF e um salário. E fizemos ainda mais, todo Diretor da empresa tem o salário inicial de 5000. Dessa forma, não precisamos escrever o construtor em todas as subclasses, podemos passar os valores para funcionário utilizado a palavra reservada base. Mas, vamos imaginar que nosso sistema precisa de modificações. A empresa decidiu dar acesso externo a clientes da empresa. E além disso, é necessário implementar uma forma de autenticação para esses clientes e para Diretores da empresa, afim de acessar dados específicos apenas visiveis para eles. Como fazer então? Teoricamente seria possivel criar uma outra classe abstrada chamada Autenticação e tanto o Cliente quanto o Diretor herdariam dessa classe. Porém, com o Diretor teríamos duas heranças, e em C# não é permitido ter heranças multiplas... então, temos que pensar em outra solução. Um novo conceito que pode nos ajudar nesta tarefa é o de interfaces:
Interfaces definem o que uma classe deve fazer e não como, podendo se assimilar a um "contrato assinado". Dessa forma, as interfaces não possuem a implementação de métodos (apenas os declaram), deixando a classe responsável por usa implementação.
Uma interface, diferente da herança, pode ser utilizada por diversas classes e podemos ter multiplas interfaces dentro de uma "subclasse". Quando usamos interface o conceito de subclasse não existe mais, pois a classe que implementa uma interface "assina um compromisso" de implementar os métodos que a interface definiu. Então, voltando ao exemplo, podemos criar uma interface para Autenticação:
public interface IAutenticavel
{
	bool Autenticar(string senha);
}
E agora a classe Diretor pode implementar esta interface:
public class Diretor : IAutenticavel, Funcionario
{
	public string Senha { get; set; }
	(...)
	public bool Autenticar(string senha)
	{
		return Senha == senha;
	}    
}

public class ClienteExterno : IAutenticavel
{
	public String Nome { get; set; }
	public String Senha { get; set; }
	public bool Autenticar(string senha)
	{
		return Senha == senha;
	}
}
A implementação do método Autenticar pode ser completamente diferente nas duas classes, inclusve podem retornar acesso a diferentes áreas, foi apenas uma conincidência (e praticidade) aparecerem iguais!

Como compilar uma aplicação C# sem o Visual Studio

A partir do Windows XP, todos os computadores com Windows possuem o compiladore instalado nativamente.

Por exemplo, neste caminho: C:\Windows\Microsoft.NET\Framework\v4.0.30319

Esta pasta possuí todos os arquivos que a VM (CLR) precisa para rodar aplicações .net na versão 4.0.30319, inclusive um arquivo chamado "csc.exe" que é uma abreviação para CSharp Compiler.

Tendo aprendido isso, podemos abrir o bloco de notas e colar o seguinte código e salve como txt, de preferencia em uma nova pasta:

using System;
class Programa
{
	static void Main(string[] args)
    {
		Console.WriteLine("Olá mundo");
    }
}

Abrir o CMD, entrar no ocal onde o arquivo foi salvo. Dentro da nova pasta onde salvamos o arquivo. digite o caminho para o compilador do C#: C:\Windows\Microsoft.NET\Framework\v4.0.30319\csc.exe NOMEDOARQUIVO.txt.

Pressione Enter.

Se formos olhar o que tem dentro do novo diretório, vamos encontrar um novo arquivo NOMEDOARQUIVO.exe.

Se voltarmos ao CMD e digitar NOMEDOARQUIVO.exe aparecerá o "Olá Mundo" que escrevemos!

C# - Considerações iniciais

Antes de começar a escrever códigos em C# é de bom tom entender o ecossitema da Microsoft suporta esta linguagem!

Antigamente, para se reescrever uma aplicação de C para VB, por exemplo, não bastava reescrever a aplicação, era necessário reescrever a biblioteca desta aplicação também. E para o caso de mudar o Sistema Operacional (SO)? Tinha que reescrever a aplicação e a biblioteca para cada SO.

Daí, começando pelo SO, a Microsoft desenvolveu uma Máquina Virtual (Virtual Machina - VM) que roda em qualquer SO (Sim, assim como Java). Dessa forma, escreveremos a aplicação para a VM e não para a máquina real (com memória RAM, processador físico.. cooler)

Dessa forma, não precisamos mais de bibliotecas e aplicações especificas para cada linguagem, podemos ter uma biblioteca e uma aplicação genérica, chamada de MSIL (Microsoft Intermediate Language), que compilará nosso código para a VM.

Em outras palavras, podemos escrever códigos em C#, VB, F# e eles serão compilados para uma aplicação escrita em MSIL que conversará com uma biblioteca MSIL. A VM conhece essa biblioteca e qualquer SO pode implementar nossa VM, sem complicações. Se quisermos ter um projeto escrito metade em C# e metade em VB, podemos, pois ambos são compilados para MSIL.

Dessa forma, temos essa hierarquia:

  • Linguagens: C#, VB, F# ...
  • Aplicação MSIL
  • Biblioteca MSIL
  • Máquina Virtual
  • Sistemas Operacionais (Windows, Linux, PS4...)
Agora, basta conhecermos os nomes específicos de cada uma das hierarquias no mundo C#. A Máquina Virtual é chamada de CLR - Common Language  Runtime. A Biblioteca MSIL é chamada de .NET Framework e a Aplicação MSIL é a aplicação .NET.

Num exemplo, o código escrito em C#:

Console.WriteLine("Olá mundo");

É compilado para um formato MSIL, tipo esse:

nop 
ldstr       "Olá mundo"
call        System.Console.WriteLine
nop  
ret

Toda linguagem .NET será compilada para esse mesmo formato que é excecutado pela CLR (ou VM). E agora, no momento da execução desse código a VM vai converter o MSIL em linguagem de máquina (linguagem que o processador entende - aquele mesmo da AMD ou Intel).

E daí vem mais um conceito, o Just-In-Time Compiler (ou Jitter) que significa que o compilador apenas executa código no momento que aplicação roda.. dessa forma, o CLR consegue compilar o código para o processador específico que a aplicação roda."

Estruturas de Repetição - While

Estruturas de repetição fazem parte do pacote básico de quem está aprendendo a programar, e ajudam no controle do fluxo de execução de determinada parte do código. É muito útil e bastante utilizado para... hum.. tudo. :)

Enquanto (while)

A estrutura mais simples, executa uma ação enquanto determinada condição for verdadeira.


Em C++/C:

while (condição)
{
    código;
    código;
    (...)
}


Podemos observar que logo depois do while, vem uma condição. Essa condição é verificada antes de entrar no "laço" de repetição e só vai parar de repetir quanto a condição se tornar falsa.
Por exemplo, vamos imprimir os números na tela começando do 100 e terminando no 0.



Entendendo o programa:


Começamos declarando uma variável inteira i e atribuímos o valor 100 a ela.
A linha seguinte é o inicio do while, a condição que usamos de parada é i ser menor ou igual a zero. Se for verdadeiro, o programa vai executar o que esta entre as chaves {}, caso for negativo o programa vai "pular" o que está entre chaves e executar o que tiver depois, se não tiver nada, é o fim do programa.
Como 100 é maior ou igual a 0, ele entra no loop. A primeira instrução é imprimir na tela o valor da variável i e quebrar uma linha (endl).
A segunda instrução no loop atribui um novo valor pra variável i, o que é importantíssimo pois ninguém quer cair num loop infinito, não é?!
Então i receberá o seu próprio valor subtraído de uma unidade, vamos fazer a conta:
i = 100 - 1;
i = 99;
Novo valor de i: 99!
Agora, o programa volta no while, e verifica a condição de novo.
(99 é maior ou igual a zero?)
É! Então ele executa as duas instruções de novo, imprimir o valor de i na tela e decrementar uma unidade do mesmo.
Isso vai acontecer até que i chegue a -1, em que a condição não será verificada e sairá do loop!
O return 0 é a instrução logo depois do loop que indica o fim do programa.

Outra possibilidade: Faça... Enquanto.

Outra forma de se utilizar o enquanto (while) é colocando sua condição de verificação (também chamada de flag) no final. Assim, o que estiver dentro do loop será executado uma vez e só se repetirá caso a condição seja verdadeira.  Dá pra ver claramente a diferença! O primeiro testa e depois executa este executa e depois testa. 


do {
   Código;
   Código;
} while(condição);
Pode ser utilizado para realizar cadastro de clientes, por exemplo. O programa pede os dados do cliente e solicita confirmação se deseja incluir mais... Enquanto o usuário desejar incluir mais cliente o programa não sairá do Loop. Essa condição pode ser enquanto o usuário não digitar zero ou clicando no botão de "ok"/"cancelar", etc
Qualquer coisa que seja fácil de implementar e você consiga fazer funcionar!!

JavaScript

Javascript, como muitos sabem (caso negativo: deveriam saber!), é uma linguagem baseada em objetos. Incorporada a páginas da web, é capaz de torná-las dinâmicas e interativas, mas tem suas limitações. Produz programas simples com aplicações limitadas, mas nem por isso insignificantes, não é mesmo?!

Antes de 1995 era chamada de LiveScript, mas quando a SUN (Sim, essa mesma que responsável pelo Java) comprou a tecnologia da Netscape,  a linguagem passou a se chamar JavaScript.

Como toda programação da web, cada browser interpreta de uma forma especifica os scripts enviados, mas na maioria dos casos, isso não interfere em muita coisa. Uma questão considerável é que o JavaScript não é considerado seguro, pois seu código fica visível em qualquer página da web.

Utilidades

  • Alterar dinâmicamente sites
  • Validar formulários
  • Trabalhar com eventos
  • Manipular Cookies, etc.

O código de JavaScript pode ser anexado em qualquer parte do conteúdo HTML, mas é uma boa prática que ele esteja dentro das tags <head></head> . Há duas formas de se incluir o código na página:

  1. Linkando um arquivo extreno, ou
  2. < script src="meuJS.js" type="text/javascript" >< /script>
  3. Colocando o código dentro da página
  4. < script type="text/javascript"> Codigo aqui < /script>

O Conceito de Objeto

Objeto é todo conjunto de elementos que pode ser finito ou infinito. Por exemplo o alfabeto é um conjunto finito, mas os números reais são infinitos. (Obs: mesmo os números sendo infinitos, há um limite nos valores os quais o computador exibe que varia de acordo com o tipo escolhido). 

O JavaScript não tem uma palavra reservada para criarmos as Classes. Talvez a melhor maneira de explicar como as classes trabalham seja comparando-as com atributos CSS. Através deles dizemos como os elementos da página se comportam. E o melhor disso é que não serve apenas a uma página específica, a mesma folha de estilos pode ser usada para inúmeras outras páginas. Da mesma forma servem as Classes. Dizemos, através delas, como os objetos devem se comportar e assim podemos criar inúmeros objetos semelhantes. 

Declaração de Variáveis

var <NomeVariavel>;

Exemplos:

var a;
var num1;
var tam;

E ai pode surgir a pergunta, mas como eu especifico um tipo de váriavel? Como o programa vai saber se eu quero manipular um inteiro ou uma cadeia de caracteres?
Simples. O JavaScript é inteligente, o valor que você atribuir a sua variável é que definirá o tipo dela, e por tanto, a coisa fica linda!! Não precisa saber float, int, bool (embora seja altamente recomendável). Só VAR é suficiente.
Mas não se engane, nem tudo são rosas.

Continua em breve (...)

Conceitos Listas

Alguns conceitos relacionados a Listas, Pilhas, Filas e Recursividade. Não há exemplos de códigos por aqui.

Listas Contíguas

São nós alocados fisicamente em posições consecutivas na memória.


Lista Simplesmente Encadeada

Contém nós que, além de armazenarem um valor, armazenam o endereço para o nó seguinte.

Lista com Descritor

Além do TAD(Tipo Abstrado de Dado) da Lista Simplesmente Encadeada, cria-se outro TAD nomeado descritor, contendo informações como: número de nós e o endereço do último nó.

Lista Simplesmente Encadeada com Descritor

Ao invés de se criar dois TADs, inclui as informações extras necessárias dentro do próprio TAD da Lista.

Lista Duplamente Encadeada

Cada nó possui informações sobre o valor, um ponteiro para o próximo nó e um ponteiro para o nó anterior.

Lista Circular

É uma lista duplamente encadeada em que os dois nós dos extremos estão unidos.

Pilhas/Filas

São listas que possuem uma disciplina de acesso.

Pilha

Todas as inclusões e exclusões de nós são feitos por uma única extremidade. Sempre desempilhamos primeiro o último nó empilhado. Esse sistema é chamado de FILO. (First In Last Out)


Fila

Todas as inclusões são feitas numa extremidade e as exclusões em outra. Sempre desenfileiramos primeiro o primeiro item enfileirado. Esse sistema é chamado de FIFO. (First In First Out)