Pesquisar neste blog

Mostrando postagens com marcador C#. Mostrar todas as postagens
Mostrando postagens com marcador C#. Mostrar todas as postagens

quinta-feira, 29 de agosto de 2013

Entendendo Structs no Microsoft.Net: memória stack e heap.

Recentemente um aluno muito aplicado me perguntou detalhes sobre a alocação de memória da estrutura de dados Structs no C# e, reuni informações interessantes sobre essa estrutura.

O artigo "C# Heap(ing) Vs Stack(ing) in .NET: Part I" mostra um modelo conceitual da estrutura da memória Stack e Heap no MS.NET:


heapvsstack1.gif

No artigo "Six important .NET concepts: Stack, heap, value types, reference types, boxing, and unboxing", o autor mostra um "teste de mesa" com diversos códigos e o respectivo efeito na memória, inclusive, com análise de tempo de alguns destes procedimentos.



Bem, esse artigo já responde a questão de qual é a memória utilizada para alocar o tipo de dados Struct, uma vez que, "Struct Types" são descendentes da classe "Value Types" a mesma dos tipos primitivos (int, bool, etc..) que são considerados estáticos e portanto irão alocar memória Stack.

No MSDN existe um comparativo entre classes e structs no artigo "Classes e estruturas (guia de programação do C#)".

No artigo "Structs (guia de programação do C#)" é possível encontrar algumas limitações dos structs em relação as classes no Microsoft.NET:
  • Em uma declaração struct, campos não podem ser inicializados a menos que eles sejam declarados como const ou static.
  • Uma struct não pode declarar um construtor padrão (um construtor sem parâmetros) ou um destruidor.
  • Structs são copiados na atribuição. Quando uma estrutura é atribuída a uma nova variável, todos os dados são copiados e qualquer modificação na nova cópia, não é refletida na estrutura original. Isso é importante lembrar-se ao trabalhar com coleções de tipos de valor, como um Dictionary < string, myStruct >.
  • Structus são tipos de valor e classes são tipos de referência.
  • Diferentemente das classes, structs podem ser instanciados sem usar o operador "new".
  • Structs podem declarar construtores com parâmetros.
  • Uma estrutura não pode herdar uma outra estrutura ou classe, e também não podem servir como base de uma classe. Todos os Structs são herdados diretamente de System.ValueType, o qual herda de System.Object.
  • Uma estrutura pode implementar interfaces.
  • Um Struct (estrutura) pode ser usada como um tipo nullable (anulável) e pode ser atribuída um valor nulo.

No artigo "struct (referência de C#)" existe um exemplo de implementação em C# de um Struct e uma definição interessante:
Um tipo struct é um tipo de valor normalmente usado para encapsular pequenos grupos de variáveis relacionadas.


Lembram do tipo "Record" do pascal (delphi)? 

No artigo "Structured Types (Delphi)" o autor faz a seguinte afirmação sobre o tipo "Record":
A record (analogous to a structure in some languages) represents a heterogeneous set of elements.

Neste outro artigo, "Understanding and Using Record Data Types in Delphi",o autor descreve o record como:
Record types define fixed collections of items of different types.

CONCLUSÃO:
"Um Struct (estrutura) é uma coleção de variáveis alocadas estaticamente na memória (Stack)."

[]´s Flavio Barbosa.






domingo, 18 de novembro de 2012

Criar e persistir controles dinamicamente em ASP.NET com C#

Uma ideia genial é a criação de controles (objetos) dinamicamente em páginas ASP.NET. Já imaginou criar um cadastro de clientes apenas configurando um conjunto de controles em uma base dados?! Essa é a proposta incipiente deste projeto. Aqui eu, Flávio Barbosa e os desenvolvedores Washington e Anderson lhes oferecemos o caminho das pedras.

Diagrama de Classe


Não há acesso a Dados, apenas foram criadas duas classes simulando a configuração, criação e persistência dos objetos dinâmicos em sessão.

Clique aqui para fazer download do projeto (213k).

quinta-feira, 16 de fevereiro de 2012

Rotina de validação de CNS e Número Provisório C# (CSharp)

Segue abaixo a classe estática CartaoNacionalSUS para validação de número CNS (Cartão Nacional de Saúde) definitivo e provisório.
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/// Inicio


using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;

/// <summary>
/// A classe estática "CartaoNacionalSUS" foi criada por Flávio Barbosa 
/// Objetivo: Validar o número do Cartão Nacional de Saúde (CNS)
/// Documento base: http://cartaonet.datasus.gov.br/downloadsNovo.asp
/// Visite também: http://www.ciaware.com.br
/// </summary>
public static class CartaoNacionalSUS
{

    /// <summary>
    /// Verifica se o número CNS informado é definitivo ou provisório e se ele é válido [FB]
    /// </summary>
    /// <param name="cns">Número de CNS a ser checado</param>
    /// <returns>True, se o número é válido; False, se for inválido.</returns>
    public static bool chkNumeroCNS(string cns)
    {
        bool result = false;

        cns = cns.Trim();


        if ((cns.Substring(0, 1) == "8") || (cns.Substring(0, 1) == "9"))
        {
            result = CartaoNacionalSUS.chkNumeroProvisorio(cns);
        }
        else
        {
            result = CartaoNacionalSUS.chkNumeroDefinitivo(cns);
        }

        return result;
    }


    /// <summary>
    /// Verifica se um número CNS provisório é válido [FB]
    /// </summary>
    /// <param name="cns">Número de CNS a ser checado</param>
    /// <returns>True, se o número é válido; False, se for inválido.</returns>
    public static bool chkNumeroProvisorio(string cns)
    {
        bool result = false;

        try
        {
            cns = cns.Trim();

            if (cns.Trim().Length == 15)
            {



                float resto, soma;

                soma=  ( ( Convert.ToInt64( cns.Substring(0, 1 ) ) ) * 15 ) +
                        ((Convert.ToInt64(cns.Substring(1, 1))) * 14) +
                        ((Convert.ToInt64(cns.Substring(2, 1))) * 13) +
                        ((Convert.ToInt64(cns.Substring(3, 1))) * 12) +
                        ((Convert.ToInt64(cns.Substring(4, 1))) * 11) +
                        ((Convert.ToInt64(cns.Substring(5, 1))) * 10) +
                        ((Convert.ToInt64(cns.Substring(6, 1))) * 9) +
                        ((Convert.ToInt64(cns.Substring(7, 1))) * 8) +
                        ((Convert.ToInt64(cns.Substring(8, 1))) * 7) +
                        ((Convert.ToInt64(cns.Substring(9, 1))) * 6) +
                        ((Convert.ToInt64(cns.Substring(10, 1))) * 5) +
                        ((Convert.ToInt64(cns.Substring(11, 1))) * 4) +
                        ((Convert.ToInt64(cns.Substring(12, 1))) * 3) +
                        ((Convert.ToInt64(cns.Substring(13, 1))) * 2) +
                        ((Convert.ToInt64(cns.Substring(14, 1))) * 1);

                resto = soma % 11;

                result = (resto == 0);
            }

        }
        catch (Exception)
        {
            result = false;
        }


        return result;
    }


    /// <summary>
    /// Verifica se um número CNS definitivo é válido [FB]
    /// </summary>
    /// <param name="cns">Número de CNS a ser checado</param>
    /// <returns>True, se o número é válido; False, se for inválido.</returns>
    public static bool chkNumeroDefinitivo(string cns)
    {
        bool result = false;

        try
        {
            if (cns.Trim().Length == 15)
            {

                float resto, soma, dv;

                string pis = string.Empty;
                string resultado = string.Empty;

                pis = cns.Substring(0, 11);

                soma = ((Convert.ToInt64(pis.Substring(0, 1))) * 15) +
                        ((Convert.ToInt64(pis.Substring(1, 1))) * 14) +
                        ((Convert.ToInt64(pis.Substring(2, 1))) * 13) +
                        ((Convert.ToInt64(pis.Substring(3, 1))) * 12) +
                        ((Convert.ToInt64(pis.Substring(4, 1))) * 11) +
                        ((Convert.ToInt64(pis.Substring(5, 1))) * 10) +
                        ((Convert.ToInt64(pis.Substring(6, 1))) * 9) +
                        ((Convert.ToInt64(pis.Substring(7, 1))) * 8) +
                        ((Convert.ToInt64(pis.Substring(8, 1))) * 7) +
                        ((Convert.ToInt64(pis.Substring(9, 1))) * 6) +
                        ((Convert.ToInt64(pis.Substring(10, 1))) * 5);


                resto = soma % 11;
                dv = 11 - resto;

                if (dv == 11)
                {
                    dv = 0;
                }

                if (dv == 10)
                {
                    soma = ((Convert.ToInt64(pis.Substring(0, 1))) * 15) +
                            ((Convert.ToInt64(pis.Substring(1, 1))) * 14) +
                            ((Convert.ToInt64(pis.Substring(2, 1))) * 13) +
                            ((Convert.ToInt64(pis.Substring(3, 1))) * 12) +
                            ((Convert.ToInt64(pis.Substring(4, 1))) * 11) +
                            ((Convert.ToInt64(pis.Substring(5, 1))) * 10) +
                            ((Convert.ToInt64(pis.Substring(6, 1))) * 9) +
                            ((Convert.ToInt64(pis.Substring(7, 1))) * 8) +
                            ((Convert.ToInt64(pis.Substring(8, 1))) * 7) +
                            ((Convert.ToInt64(pis.Substring(9, 1))) * 6) +
                            ((Convert.ToInt64(pis.Substring(10, 1))) * 5) + 2;

                    resto = soma % 11;
                    dv = 11 - resto;
                    resultado = pis + "001" + Convert.ToString(Convert.ToInt16(dv)).Trim();
                }
                else
                {
                    resultado = pis + "000" + Convert.ToString(Convert.ToInt16(dv)).Trim();
                }


                result = cns.Equals(resultado);

            }
        }
        catch (Exception)
        {
            result = false;
        }


        return result;
    }

 

}

/// Fim

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////