Tags: , | Categories: C#, Linguagem de Programação Posted by Rafael on 12/04/2011 18:27 | Comentários (0)

Olá pessoal,

Vejam só que notícia bacana para aqueles que programam em C#: http://tirania.org/blog/archive/2011/Apr-06.html

Enjoy it, Cool

Até mais!

Tags: , , | Categories: C#, Linguagem de Programação Posted by Rafael on 11/01/2011 19:03 | Comentários (1)

Olá pessoal!

Falaremos hoje sobre operadores C#, em especial sobre os operadores shift, << e >> . A função desses operadores é deslocar bits para a esquerda ( << ) ou para a direita ( >> ), que podem ser utilizados apenas em operações com variáveis do tipo inteiro, pois, não existem números reais na base 2 (binários), apenas números inteiros.

Para entender melhor, vamos falar um pouco sobre números binários e inteiros.

Consideremos a seguinte tabela:

Essa é uma tabela para facilitar a representação de números inteiros em binários. Na linha superior (em azul) temos o expoente da base. Como a base que iremos trabalhar é binária, ou seja, base 2, a linha amarela representa o resultado da potenciação entre a base 2 e seus expoentes. Assim, temos 20 = 1, 21 = 2, 22 = 4, 23 = 8, ..., 210 = 1024, ..., e assim por diante (limitei até o expoente 10 apenas para facilitar a exemplificação).

Muito bem, agora, vamos representar o número inteiro 100 em binário. Na linha amarela, partimos sempre da esquerda para a direita, até encontrar o primeiro número menor ou igual ao número que queremos representar, que nosso caso é o inteiro 100.

Localizamos que o número 64 é o primeiro número menor ou igual a 100, da esquerda para a direita. Assim, “ligamos” o flag, ou seja, inserimos o número 1, da seguinte maneira:

Feito isso, partimos para o segundo bit. Devemos ter em mente o quanto resta para chegarmos a 100 inteiros. A conta é bem simples: se já “ligamos” o 64, a subtração entre 100 e 64 é igual a 36. A partir de agora, localizamos o primeiro número menor ou igual a 36, a partir da primeira célula à direita do flag que representa 64, que é 32.

Como 32 é menor ou igual a 36, ativamos também essa célula, ficando assim:

Legal, agora nos restam 4 inteiros (100 – 64 – 32 = 4). Dando seqüência, como 16 não é menor ou igual a 4, inserimos um 0, ou seja, “desligamos” o flag da célula 16, assim:

Da mesma maneira, fazemos com a célula 8, pois 8 não é menor ou igual a 4, ficando assim:

Como 4 é menor ou igual a 4, “ligamos” o flag, da seguinte maneira:

Como chegamos a 100 inteiros, completamos as células restantes à direita com 0, assim:

Temos agora o número inteiro 100 representado em binário como 1100100.

Muito bom! Agora que já sabemos como representar inteiros em binários de uma forma fácil, vamos entender como os operadores shift trabalham.

Basicamente, como dito anteriormente, o operador shift << desloca um bit à esquerda, inserindo um 0 (zero) na célula vazia, e o operador >> desloca um bit à direita, desconsiderando o bit que “sai” do range. Vamos exemplificar com um Console Application em C#, bem simples, junto com a nossa tabela de conversão.

Consideremos o seguinte Console Application:

namespace Blog.Operadores.Shift

{

    class Program

    {

        static void Main(string[] args)

        {

            try

            {

                Console.WriteLine("Insira um número inteiro:");

 

                int inteiro = 0;

                Int32.TryParse(Console.ReadLine(), out inteiro);

 

                Console.WriteLine("Número inteiro escolhido: " + inteiro.ToString());

 

                Console.WriteLine("");

 

                Console.WriteLine("Quantos bits você deseja deslocar?");

 

                int qtdeBits = 0;

                Int32.TryParse(Console.ReadLine(), out qtdeBits);

 

                Console.WriteLine("Bits a deslocar: " + qtdeBits.ToString());

 

                Console.WriteLine("");

 

                Console.WriteLine("À esquerda ou à direita? Digite << para à esquerda e >> para à direita:");

 

                string comando = Console.ReadLine();

 

                if (comando.Trim() != "<<" && comando.Trim() != ">>")

                {

                    throw new Exception("Comando inválido! Você deve escolher entre << e >>");

                }

 

                switch (comando.Trim())

                {

                    case "<<":

                        Console.WriteLine("Bit deslocado à esquerda");

                        inteiro = inteiro << qtdeBits; // forma simplificada: inteiro <<= qtdeBits;

                        break;

                    case ">>":

                        Console.WriteLine("Bit deslocado à direita");

                        inteiro = inteiro >> qtdeBits; // forma simplificada: inteiro >>= qtdeBits;

                        break;

                    default:

                        break;

                }

 

                Console.WriteLine("");

                Console.WriteLine("Resultado: " + inteiro.ToString());

            }

            catch (Exception ex)

            {

                Console.WriteLine("");

                Console.ForegroundColor = ConsoleColor.Red;

                Console.WriteLine("ERRO: " + ex.Message);

            }

            finally

            {

                Console.ResetColor();

                Console.ReadKey();

            }

        }

    }

}

Se preferir, faça o download do projeto aqui: Blog.Operadores.Shift.zip (19,21 kb)

Note os dois comentários // forma simplificada no código. Podemos escrever tanto assim x = x << y quanto x <<= y ou então x = x >> y quanto x >>= y. A segunda opção é a forma simplificada do comando. Muda apenas a sintaxe, o resultado é o mesmo.

Ao executarmos o aplicativo, temos a seguinte tela:

Para seguir o nosso exemplo, vamos inserir o número 100.

Vamos deslocar apenas 1 bit à esquerda.

Na tabela, podemos ver como pode ser feito manualmente:

Todos os bits são deslocados 1 (uma) casa para a esquerda, e a célula vaga é preenchida com 0 (zero).

Assim, temos o número inteiro 200 como resultado. Agora vamos executar novamente o aplicativo, porém, agora deslocando 1 bit à direita.

Na tabela:

Obtemos como resultado 50 inteiros.

Logo, podemos notar que, se deslocarmos 1 bit à esquerda, multiplicamos o número por 2, e se deslocar à direita, dividimos também por 2. Agora, porque por 2? A resposta é bem simples, como estamos trabalhando com binários, ou seja, base 2, o deslocamento de bits multiplica ou divide o valor pela base, que é 2.

Agora, se deslocarmos 3 bits à direita de 100, temos como resultado 12. Você pode me perguntar: porque não 12,5? A resposta também é simples: porque não existem números reais por representação de bits, ou seja, o resultado 12,5 é truncado, ficando apenas 12.

Vamos ver na tabela:

E na aplicação:

É isso aí.

Até a próxima!

Tags: , , | Categories: C#, Linguagem de Programação Posted by Rafael on 12/10/2010 23:19 | Comentários (0)

Quando declaramos variáveis de tipos nativos em C#, sempre um valor default é associado às mesmas. Veja o código abaixo.

As variáveis foram declaradas, e note na coluna Value que cada uma recebeu um valor padrão. Isso, em determinadas situações, pode ser um problema. Imagine que você deseja persistir um objeto em uma tabela do banco de dados, e que, alguns campos dessa tabela permitem a inserção de valores nulos. Na compilação não teremos problemas, porém, uma exception será disparada em tempo de execução, se tentarmos atribuir um valor nulo à alguma propriedade do nosso objeto.

Para resolvermos esse problema, utilizamos os nullable types. Muito simples e fácil, basta inserirmos o símbolo ? à direita do tipo da variável, assim:

Notem na coluna Value que o valor atribuído a cada variável é null, ao invés do valor padrão de cada tipo. Assim, podemos atribuir valores nulos ao nosso objeto, e persisti-lo sem problemas.

Simples assim.

Até a próxima!

Tags: , , | Categories: C#, Linguagem de Programação Posted by Rafael on 12/10/2010 21:37 | Comentários (0)

Dando seqüência à série Operadores C#, vamos falar sobre os operadores de incremento (++) e decremento (--) de variáveis.

Operadores de incremento e decremento de variáveis

O conceito de operadores de incremento e decremento é muito simples. Basicamente, utilizamos o operador de incremento para simplificar a expressão “variável = variável + 1”, ou então o operador de decremento para simplificar a expressão “variável = variável - 1”. O trecho de código abaixo ilustra a sintaxe dos operadores:

    int x = 0;



    // incrementando a variável x

    x = x + 1;



    // incrementando a variável x, utilizando o operador de incremento

    x++;



    // decrementando a variável x

    x = x - 1;



    // decrementando a variável x, utilizando o operador de decremento

    x--;

 

Muito simples e fácil de entender. Agora, consideremos o seguinte trecho de código:

    class Program

    {

        static void Main(string[] args)

        {

            int x = 0;

            int y = 0;

            Console.WriteLine("1º loop:");

            for (int i = 0; i < 5; i++)

            {

                if (x++ == 2)

                {

                    Console.WriteLine("Entrou no if da variável x++");

                }

                if (++y == 2)

                {

                    Console.WriteLine("Entrou no if da variável ++y");

                }

            }

            Console.WriteLine();

            x = 5;

            y = 5;

            Console.WriteLine("2º loop:");

            for (int i = 0; i < 5; i++)

            {

                if (x-- == 2)

                {

                    Console.WriteLine("Entrou no if da variável x--");

                }

                if (--y == 2)

                {

                    Console.WriteLine("Entrou no if da variável --y");

                }

            }

            Console.ReadKey();

        }

    }

 

Vemos que no primeiro loop, as variáveis x e y são incrementadas, porém de maneiras diferentes. A variável x é incrementada após a execução da instrução if (x++ == 2), e a variável y é incrementa antes da execução da instrução if (++y == 2). O mesmo acontece no segundo loop, só que, ao invés das variáveis serem incrementadas, elas são decrementadas. No código acima, utilizamos as mesmas condições dos ifs para demonstrar que as variáveis com operador à esquerda são incrementadas ou decrementadas antes da execução da instrução, e as variáveis com operador à direita são incrementadas ou decrementadas após a execução da instrução. Ao executarmos o código, temos a seguinte saída:

Muito simples e fácil. Espero ter ajudado!

Até a próxima!

Tags: , , | Categories: C#, Linguagem de Programação Posted by Rafael on 10/10/2010 8:02 | Comentários (0)

Apesar de parecer um assunto para iniciantes na linguagem, me surpreendi um dia, junto com um colega de trabalho, descobrindo alguns operadores da linguagem C#, que eu nunca havia utilizado antes. Então, mesmo que você já domine a linguagem C#, de alguma forma, esse post pode ser útil.

Com esse post, inicio uma série de posts sobre operadores C#. Nesse primeiro, vamos falar sobre os operadores lágicos & (and) e | (or) e seus respectivos condicionais && e ||.

Diferença entre os operadores "& e &&" e/ou "| e ||"

Consideremos o seguinte trecho de código:

    class Program

    {

        static void Main(string[] args)

        {

            int x = 0;

            for (int i = 0; i < 10; i++)

            {

                if (false & ++x == 2)

                {

                    // ...

                }

            }

        }

    }

Se inserirmos um breakpoint no código e o debugarmos, veremos que a variável x é incrementada (o incremento de variáveis será abordado no próximo post), mesmo se a condição não for verdadeira:

Porém, se substituirmos o operador & pelo &&, o código ficará assim, e notaremos que a variável x não é alterada.

O mesmo comportamento se repete para os operadores | e ||:

Com o operador |

Agora, substituindo o operador | pelo ||

Com isso, concluímos que quando utilizamos os operadores & e |, todas as partes da condição são verificadas. Notamos isso pois a variável x é incrementada. Porém, quando utilizamos os operadores && e ||, a variável não é incrementada. Isso ocorre porque a verificação é executada da esquerda para a direita, por exemplo, if ( 1ª verificação && 2ª verificação && 3ª verificação ), e, caso a primeira parte (ou segunda parte) da condição seja válida (entenda como condição válida a condição verdadeira para entrada ou não do if), as demais não são verificadas, como observamos nos exemplos acima, ou seja, não é necessária a validação completa da condição.

Bom, é isso.

Espero que tenham gostado.

Até a próxima!