1. Introdução        2

2. Embasamento Teórico        2

2.1 A linguagem de programação c#        2

2. 2 Ambiente de desenvolvimento utilizado        2

3. Parâmetros in, out e ref        3

3.1 Out        3

3.2 Ref        4

4. Classes genéricas        5

4.1 Classes genéricas        5

4.2 Struct        6

5. Coleções Type-safe        7

6. Serialização de dados        8

6. Objeto dinâmico        9

7. Delegates e eventos        11

7.1 Delegates        11

7.2 Eventos        14

8. Conclusão        18

9. Bibliografia        19


1. Introdução

Essa atividade tem como objetivo reunir as principais características da linguagem de programação c#. Abordando funcionalidades como classes genéricas, serialização de dados e passagem de parâmetros com as palavras reservadas in,out e ref.

Cada seção possui códigos explicativos para aumentar a compreensão dos tópicos apresentados e quando necessário links com as fontes são providos para o leitor.

2. Embasamento Teórico

2.1 A linguagem de programação c#

A linguagem de programação C# faz parte do Framework .NET, mas nem sempre teve esse nome. De acordo com  Yuri Pacievitch o C# tinha um nome diferente no seu começo.

Esta linguagem foi desenvolvida com o nome de Cool. No momento do lançamento da plataforma .NET, mudaram o nome da linguagem para C#. A criação da linguagem C# ajudou muito no desenvolvimento do .NET, pois a plataforma não precisou se adequar a nenhum código de alguma linguagem já existente.

Fonte: http://www.infoescola.com/informatica/c-sharp

2. 2 Ambiente de desenvolvimento utilizado

A microsoft disponibiliza o Visual Studio como a sua principal ferramenta para criar aplicações que utilizam tecnologia .NET. Nos últimos anos o Visual Studio era o único meio de desenvolver tais aplicações e a utilização do Windows era obrigatória.

Recentemente a Microsoft junto com a mudança de seu CEO anunciou algumas mudanças drásticas na cultura da empresa e de grande impacto no mundo da tecnologia. Um dos anúncios foi a entrada da Microsoft na Linux Foundation, a organização que mantém o Linux em constante desenvolvimento e a aderência maior na comunidade open source. Com esse intuito de ganhar espaço no open source foi lançado o Visual Code, uma nova ferramenta de programar para a plataforma .NET(e outras linguagens) que exige muito menos requerimentos para ser utilizado e é de código aberto.

3. Parâmetros in, out e ref

"1. Parâmetros de métodos: in, out, ref. Descrever as diferenças e quando é conveniente a utilização de cada um deles."

3.1 Out

A palavra reservada out força o argumento em questão a ser passado como referência, é bem parecido com  a palavra reservada ref porém, out, não necessita ter uma variável inicializada para ser passada como argumento.

using System;

namespace ConsoleApplication

{

    public class Program

    {

        public int sum(out int a, out int b)

        {

            a = 10;

            b = 10;

            return a + b;

        }

        public static void Main(string[] args)

        {

            Program exec = new Program();

            // Declara a variável mas não a inicializa

            int a;

            int b;

            // realiza a soma

            Console.Write(exec.sum(out a, out b));

            /*

             * Como passamos por referência cada uma das variáveis

             * possuem o valor 10

             */

            Console.Write(a);

            Console.Write(b);

        }

    }

}

Mas atenção, é necessário assinar o valor da variável antes de utiliza-la. Veja que atribuímos o valor 10 para a variável a e para a variável b.

3.2 Ref

A palavra reservada ref deve ser utilizada quando desejamos passar uma variável por referência, ao utilizar ref, é obrigatório que a variável seja inicializada como demonstra o exemplo a seguir

using System;

namespace ConsoleApplication.In

{

    public class Program

    {

        public int sum(ref int a, ref int b)

        {

            /*

             * Não precisamos mais inicializar a variável dentro

             * do método, pois ref garante uma variável inicializada

             *

             * a = 10;

             * b = 10;

             */

            return a + b;

        }

        public static void Main(string[] args)

        {

            Program exec = new Program();

            /*

             * Declara a variável e inicializa, ao contrário do out

             * ao utilizar ref é obrigatória a inicialização da variável

             */

            int a = 0;

            int b = 0;

            // realiza a soma

            Console.Write(exec.sum(ref a, ref b));

            /*

             * Como passamos por referência cada uma das variáveis

             * possuem o valor 10

             */

            Console.Write(a);

            Console.Write(b);

        }

    }

}

Qualquer alteração dentro do método sum que modifiquem as variáveis passados como parâmetro, será persistido fora do seu escopo.

4. Classes genéricas

"2. Classes Genéricas: definição de parâmetros gerais e suas restrições: class, struct, where, entre outros, além do termo in usado na parametrização (exemplo: class MyClass<in T>)"

4.1 Classes genéricas

Classes genéricas encapsulam operações que não são de um tipo definido. O uso mais comum para classes genéricas são coleções como linked list, hash tables, stacks, queues entre outros.

Operações como adicionar e remover elementos são comuns a todas coleções sendo diferente apenas o tipo de dado a ser manipulado.

O framework .NET possui inúmeras classes genéricas para serem utilizadas como as citadas a cima, List, Queue, LinkedList etc. Para ver a lista completa basta acessar o link da documentação em https://msdn.microsoft.com/en-us/library/system.collections.generic.aspx.

using System;

namespace ConsoleApplication.Generics

{

    // Definição de uma classe "normal", sem ser genérica

    class Base { }

    // Definição de uma classe genérica

    class BaseGenerica<T> { }

    public class Program

    {

        public static void Main(string[] args)

        {

            // Não é possível especificar qual será o tipo de dado a ser manipulado

            Base base1 = new Base();

            // Com classes genéricas é possível especificar qual tipo de dado será manipulado

            BaseGenerica<int> baseGenericaInt = new BaseGenerica<int>();

            BaseGenerica<string> baseGenericaString = new BaseGenerica<string>();

        }

    }

}

4.2 Struct

Struct é  geralmente utilizado para encapsular grupos pequenos de dados relacionados, como as coordenadas de um retângulo, as propriedades de um produto ou até mesmo os meses do ano.

using System;

namespace ConsoleApplication.Struct

{

    public struct Livro

    {

        public string titulo;

        public string autor;

        public int anoPublicacao;

    }

    public class Program

    {

        public static void Main(string[] args)

        {

            Livro csharp;

            csharp.titulo = "Csharp";

            csharp.autor = "Desconhecido";

            csharp.anoPublicacao = 2017;

            Console.WriteLine(csharp.autor);

            Console.WriteLine(csharp.titulo);

        }

    }

}

5. Coleções Type-safe

"3. Coleções Type-Safe: o que são? Qual a diferença das demais coleções?"

A idéia de Type-Safe(Tipo-Seguro) significa em geral, a característica do código que permite ao desenvolvedor ter a certeza de que um valor ou objeto exibirá certas propriedades (ou seja, ser de um certo tipo) para que isso possa ser utilizado de uma maneira específica sem medo de comportamento inesperado ou indefinido.

Por exemplo, em C #, você poderia dizer que a classe ArrayList não é segura porque pode armazenar qualquer objeto, o que significa que você pode fazer algo como o seguinte:

using System;

using System.Collections;

namespace ConsoleApplication.CollectionsTypeSafe

{

    public class Program

    {

        public static void Main(string[] args)

        {

            var integers = new ArrayList();

            integers.Add(1);

            integers.Add(2);

            integers.Add("3"); // um erro ocorrerá em tempo de execução

            for (int i = 0; i < integers.Count; ++i) {

                int integer = (int)integers[i];

            }

        }

    }

}

O exemplo acima será compilado porque o valor "3", mesmo que seja uma seqüência de caracteres e não um inteiro. No entanto, ele lançará um InvalidCastException quando você tentar converter uma string para um inteiro porque um String não pode ser convertido em um Int32.

E para resolver esse problema utilizamos type-safe, veja como ficaria o código aplicando essa técnica.

using System;

using System.Collections.Generic;

namespace ConsoleApplication.CollectionsTypeSafe.Generic

{

    public class Program

    {

        public static void Main(string[] args)

        {

            List<int> integers = new List<int>();

            integers.Add(1);

            integers.Add(2);

            // integers.Add("3"); não é mais possível utilizar pois a lista só aceita inteiros

            for (int i = 0; i < integers.Count; ++i) {

                int integer = (int)integers[i];

            }

        }

    }

}

Porém a classe List <T> é type-safe - ou seja, qualquer valor ao qual o desenvolvedor acessar dentro dessa lista, será garantido que será do tipo <T> (no nosso exemplo <int>, só valores inteiros). E você pode, portanto, ter certeza de que você será capaz de executar operações como casting.

6. Serialização de dados

"4. Serialização de Dados: quando usar? como usar? Apresentar exemplos usando Streams

I/O."

Em ciência da computação, no contexto de armazenamento e transmissão de dados, a serialização é o processo de salvar ou transliterar um objeto em outro em um meio de armazenamento (como um arquivo de computador ou um buffer de memória) ou transmiti-lo por uma conexão de rede, seja em forma binária ou em formato de texto como o XML ou JSON. Esta série de bytes pode ser usada para recriar um objeto com o mesmo estado interno que o original.

Fonte: http://bit.ly/2lYmtkh 

Com C# conseguimos serializar objetos de diferentes formas como JSON, texto e XML. No exemplo a seguir é demonstrado como serializar um objeto Book.

using System;

using System.Xml.Serialization;

namespace ConsoleApplication

{

    public class Program

    {

        public static void Main(string[] args)

        {

             Book overview = new Book();

            overview.title = "Serializando meu objeto";

           

            XmlSerializer writer = new XmlSerializer(typeof(Book));

            var path = "./ObjetoSerializado.xml";

            System.IO.FileStream file = System.IO.File.Create(path);

            writer.Serialize(file, overview);

            /*

             * Geralmente o método CLose é invocado para finalizar

             * a manipulação do stream, mas em ambientes híbridos onde

             * é possível utilizar o dotnet core como MAC OS ou Linux

             * o método a ser invocado é o Dispose

             */

            file.Dispose();

        }

    }

}

6. Objeto dinâmico

"5. Objetos dinâmicos (a palavra dynamic). Qual a diferente deste tipo e do tipo object?"

O tipo dynamic é um tipo estático que é definido pela palavra reservada dynamic sendo que a princípio a variável desse tipo pode ser TUDO, e, em tempo de compilação o tipo dynamic assume qualquer operação.

Mesmo sendo um tipo estático a declaração dynamic faz com que o compilador não realize as validações estáticas sendo que as operações também somente serão avaliadas em tempo de execução.

Fonte: http://www.macoratti.net/11/02/c_din1.htm 

O seguinte exemplo resultará em um erro de compilação, pois não é possível aplicar o operador += em um objeto, apenas em valores numéricos.

using System;

namespace ConsoleApplication

{

    public class Program

    {

        public static void Main(string[] args)

        {

             object teste = "Object";

            teste += 1;

        }

    }

}

Porém em alguns casos é necessário utilizar tal técnica, e para isso podemos utilizar objetos dinâmicos, veja o mesmo exemplo a seguir porém sem nenhum erro em tempo de compilação e execução

using System;

namespace ConsoleApplication

{

    public class Dynamic

    {

        public static void Main(string[] args)

        {

             dynamic teste = "Object";

            teste += 1;

            Console.WriteLine(teste); // O resultado será "Object1"

        }

    }

}

Macoratti define bem  o que é cada tipo e seu propósito, a tabela abaixo foi construída de forma a ajudar e clarificar quando utilizar cada tipo.

Dynamic

Fornece um meio para armazenar qualquer valor que só é conhecido em tempo de execução.

Object

Uma maneira simples de armazenar valores em um objeto sem classe

var

É uma forma de inferir um tipo e somente variáveis podem ser declaradas;

Além disso em seu texto, é possível entender claramente o objetivo de possuir esse recurso na linguagem e como outras linguagens como PHP e Javascript resolvem isso.

O lado positivo de se usar dynamic é a facilidade de não ter que seguir a tipagem estrita da linguagem, embora isso seja controverso pois c# se diz uma linguagem type-safe, isso da um poder enorme nas mãos dos programadores.

Esse poder pode ser julgado de duas formas, uma a da maneira positiva porém isso também pode ser visto por um lado negativo. Pois o compilador deixa tudo na mãos do programador e deixa a seu cargo garantir que nenhum erro de execução seja lançado.

7. Delegates e eventos

"6. Delegates e Eventos: qual a diferença? Em que ponto eles são equivalentes?"

7.1 Delegates

Um delegate é uma referência a um método de uma determinada classe, com essa característica é possível desacoplar o código que escrevemos.

Então um delegate em C#, é semelhante a um ponteiro de função (a vantagem é que é um ponteiro seguro). Usando um delegate você pode encapsular a referência a um método dentro de um objeto de delegação. O objeto de delegação pode ser passado para o código o qual pode chamar o método referenciado sem ter que saber em tempo de compilação qual método será chamado.

Fonte: http://www.macoratti.net/11/05/c_dlg1.htm 

 

O exemplo a seguir ilustra como utilizar de maneira simples o delegate em uma classe. Nesse exemplo criamos um ponteiro para o método LimparGrama, e repare que mesmo sendo privado conseguimos executa-lo graças ao delegate.

using System;

namespace ConsoleApplication

{

   

    public class Casa

    {

        public delegate void CortarGrama();

        private static void LimparGrama()

        {

            Console.WriteLine("Cortando grama");

        }

        public static void Main(string[] args)

        {

            CortarGrama invocarDelegate = new CortarGrama(LimparGrama);

            invocarDelegate();

        }

    }

}

Ao executar o código a seguir é exibido "Cortando grama" no console da aplicação, mas é importante se atentar a alguns detalhes.

A declaração de um delegate deve seguir alguns princípios básicos, em sua assinatura devemos informar a sua visibilidade, qual o tipo de retorno, o nome do método e por fim seus parâmetros.

Obs: se a visibilidade for omitida o delegate assumirá public

Para ficar mais claro, a seguir são exibidos alguns exemplos de declaração errada de um delegate.

private delegate MeuDelegate();

delegate CortarGrama();

A seguir são exibidas algumas declarações válidas para a assinatura de um delegate

protected delegate void CortarGrama(object sender);

public delegate void CortarGrama();

delegate void CortarGrama();

public delegate String CortarGrama();

7.2 Eventos

Eventos é um conceito implementado na maioria das linguagens de programação existentes. Um evento é uma ação criada/reconhecida pelo software que pode ou não ser tratada pelo software.

Em outras palavras, um evento pode ser um click de um botão. Se imaginarmos uma interface gráfica onde o usuário pode clicar e disparar um evento de clique, esse seria uma ação gerada pelo usuário mas reconhecida pelo software. Como resultado poderíamos ter uma nova tela se abrindo com informações que o usuário necessita, essa etapa seria o software entendendo o evento e tratando-o.

Em computação, um evento é o resultado de uma ação. A ocorrência de um evento pode provocar uma reação, que seria uma ação (ou conjunto de ações) a ser tomada.

Fonte: https://pt.wikipedia.org/wiki/Evento_(computa%C3%A7%C3%A3o) 

Para trabalhar com eventos temos a palavra reservada event e delegate. As aplicações desenvolvidas em .NET são baseadas em mensagens o que significa que a aplicação se comunica através de mensagens.

O Receiver ou Handler, é quem está esperando a mensagem do evento e é aqui que os delegates entram em ação.

O Sender é o responsável por enviar o evento, se tomarmos como base o exemplo do clique, o mouse seria o responsável por enviar o evento.

O código a seguir ilustra um ciclo de evento disparado e tratado pelo software. Iremos simular a ação de encodar um video e logo em seguida disparar um evento para enviar uma mensagem de texto para notificar que a manipulação do video foi finalizada.

A primeira coisa que vamos criar é uma classe Video, para representar a abstração de um arquivo de video no nosso código.

using System;

namespace ConsoleApplication

{

    public class Video

    {

        public String Titulo {get; set;}

    }

}

A segunda coisa que iremos fazer é criar uma classe que irá disparar o evento e gerenciar a manipulação do video, chamaremos essa classe de VideoEncoder

using System;

namespace ConsoleApplication

{

    public class VideoEncoder

    {

        // Define o delegate para gerenciar o evento

        public delegate void VideoEncodado(object sender, EventArgs args);

       

        // Cria o evento para ser desparado

        public event VideoEncodado videoEncodado;

        // Começa o processo

        public void Encodar(Video video)

        {

            System.Console.WriteLine("Encodando video " + video.Titulo + " ...");

             OnAcabouDeEncodar();

        }

        protected virtual void OnAcabouDeEncodar()

        {

            if (videoEncodado != null)

            {

                videoEncodado(this, EventArgs.Empty);

            }

        }

    }

}

Não podemos esquecer da nossa classe que irá executar todo esse código, chamaremos ela de Program e ela se encarregará de ser o ponto de entrada para a execução de todo esse código.

using System;

namespace ConsoleApplication

{

    public class Program

    {

        public static void Main(string[] args)

        {

            var video  = new Video() { Titulo = "Meu filme" };

            // Essa classe é quem dispara o evento

            var encoder = new VideoEncoder();

            // Começa o processo

            encoder.Encodar(video);

        }

    }

}

Repare que na classe Program temos o código que de fato cria os nossos objetos a serem manipulados. Até o momento temos um programa funcional que ao executar exibirá a mensagem "Encodando video Meu filme", temos também o nosso código que verifica se existem algum objeto registrado que deseja receber a notificação quando o video finaliza sua tarefa(esse código está dentro da classe VideoEncoder).

Como não temos nenhum objeto para executar o nosso evento, nada acontece ao finalizar o encode. Vamos registrar então uma classe chamada Mensagem, para disparar uma mensagem ao finalizar o encoding do video.

A primeira coisa que devemos fazer é criar uma classe chamada Mensagem e implementar o método OnAcabouDeEncodar.

using System;

namespace ConsoleApplication

{

   

    public class Mensagem

    {

        public void OnAcabouDeEncodar(object sender, EventArgs args)

        {

            System.Console.WriteLine("Enviando mensagem");

        }

    }

}

Temos finalmente uma classe que irá receber o evento disparado e enviar uma mensagem. Mas para que o nosso código funcione devemos alterar também a classe Program.

Nela iremos registrar a classe Mensagem como uma classe que irá ficar aguardando a notificação do evento.

using System;

namespace ConsoleApplication

{

    public class Program

    {

        public static void Main(string[] args)

        {

            var video  = new Video() { Titulo = "Meu filme" };

            // Essa classe é quem dispara o evento

            var encoder = new VideoEncoder();

            // Irá "escutar o evento" e trata-lo enviando uma mensagem

            var tratar = new Mensagem();

           

            encoder.videoEncodado += tratar.OnAcabouDeEncodar;

            // Começa o processo

            encoder.Encodar(video);

        }

    }

}

Repare que criamos um novo objeto Mensagem, e registramos ele para ser notificado assim que o evento de encodar o video acabar.

Screen Shot 2017-02-26 at 21.25.35.png

Como podemos ver delegate e events são relacionados. Em resumo delegates são formas de apontar para métodos de tal forma que consigamos desacoplar alguma lógica específica para ser utilizada.

Já os eventos são ações criadas/reconhecidos pelo software para cumprir determinada tarefa que se utilizam de delegates.


8. Conclusão

Embora o nome da matéria seja "Introdução a plataforma .NET", com esse artigo fica claro que fomos muito além da "introdução". Tópicos como Coleções Type-safe e Generics são tópicos da certificação Microsoft e que muitos programadores que manipulam a linguagem diariamente as vezes não tem conhecimento do conteúdo apresentado aqui.

Partes importantes como delegates e eventos foram abordados de uma forma simples e direta, trazendo exemplos concretos e que fazem sentido para o contexto apresentado.

Apesar do conteúdo apresentado ser de muito valor para quem deseja entender um pouco melhor os tópicos apresentados, não foi possível apresentar de maneira profunda cada tópico. Por esse motivo fontes foram adicionadas para sempre que necessário sejam consultadas.


9. Bibliografia