none
Duvidas sobre <T> em programação C#..!! RRS feed

  • Pergunta

  • Em primeiro lugar, uma boa tarde pra quem estiver lendo este Threads..!

    É o seguinte galera, estava navegando entre a biblioteca de Classes do C#, e vi em algumas classes esse <T> ou T, e pesquisei na .net e vi que tem algo haver com lista generica..!

    Vi tbm alguns Crud de exemplo na net e vi que é bem util e eficiente a utilização do mesmo..!

    Mas realmente tem haver com lista generica..?

    Como utiliza-lo..?

    Qual sua função..?

    Atenciosamente

    André

    terça-feira, 5 de março de 2013 16:24

Respostas

  • Isso é genérics amigo. 

    A ideia é escrever códigos genéricos, que funcionem para vários tipos de objetos sem precisar replicar o código. 
    Como você sabe, o c# é fortemente tipado, ou seja, se houver uma lógica que pode ser aplicada a várias classes, você teria que escrever essa classe várias vezes mudando apenas o TIPO de dados.

    Com generics você contorna isso, criando códigos para tipos que serão definidos no momento que for instanciar ou herdar uma classe. 

    public interface IBaseCRUD<T>

    O T é um apelido que você da ao tipo que você definir que será o T, pode ser qualquer nome, 
    ex:

     public interface IBaseCRUD<MeuTipo> 

    para utilizar essa interface, você precisa definir um tipo de dados para o tipo generico "<T>":

    ex: 
    Public class teste: IBaseCRUD<Model.Pessoa> // uma classe que implementa a interface.

    Nesse caso, todos os metodos definidos como "<T>" na interface irão se transformar em "Model.Pessoa".

    Um exemplo funcional para isso é a lista generica do .net LIST<T>.
    O que essa lista faz? simplesmente cria um arrayList tipado com o tipo definido em T.

    Ou seja, pra fazer uma lista tipada sem o generic "<T>", você teria que criar uma classe para cada tipo de dados do .net... ou seja stringList, intList, booleanList, etc... 
    E essas listar terão a mesma implementação no seu interior... ou seja, replicará o código dezenas de vezes... 

    Agora com generics, você cria a lógica que funciona em qualquer tipo de dados, simplesmente não definindo um Tipo de dados mas sim permitindo que você passe o tipo de dados que a lista receberá:

    ex: List<String>, List<Int>, List<bool>, List<Model.Pessoa> etc...

    O "WHERE" serve para definir regras de tipagem... exemplo em portugues:

    Você quer somente tipos de dados que implementem uma interface.
    Você quer criar uma logíca para seus objetos que utilizem uma classe base.
    Você precisa ter acesso a algumas propriedades do objeto.

    O mais importante, acredito que seja ter acesso a propriedades... como assim? 

    quando você define o "<T>" você não sabe que tipo de dados será definido a ele... ou seja... se tiver uma classe base com propriedades que você precisa utilizar na sua classe generica... você precisa dizer com o WHERE que sua classe "<T>" herda de PessoaBase... nesse caso, quando você fizer:

    public class Pessoa<T> where T:PessoaBase

    voce poderá acessar as propriedades da pessoa Base, ex:

    public class Pessoa<T> where T:PessoaBase
    {

    public void teste<T>(T pessoa)
    {
        int idPessoa = pessoa.IdPessoa; // dizendo que o T é uma pessoa base, você pode fazer isso.

    //etc...

    }
    }

    para curiosidade... se quiser retornar um tipo de dados padrão nos seus métodos utlizando generic... como exemplo, não encontrou nada e você não pode retornar null porque não se sabe se o tipo será um reference type (objeto) ou value type(string, int etc)... 
    você pode fazer:

    return default(T); 

    se T for um objeto retornará null
    se T for um value type, retornará o tipo padrão: ex: int =0; string = null ou emptystring; bool = false; datetime = datetime.MinValue, etc...



    Desenvolvedor de sistemas VB6, ASP, ASP.NET, C#, VB.NET, SQL Server, Oracle e MySql.


    quarta-feira, 6 de março de 2013 00:17

Todas as Respostas

  • Eu uso List Generic <T>

    Crio a interface com as assinaturas dos métodos:

      public interface IBaseCRUD<T>
        {
            void Add(T pEntity);
            void Delete(T pEntity);
            void Attach(T pEntity);
            void Detach(T pEntity);
            void Update(T pEntity);
            IQueryable<T> GetAll();
            IQueryable<T> Find(Expression<Func<T, bool>> where);
            void SaveChanges();
    
        }


    Depois crio a classe utilizando as assinaturas:

     public class AbstractCRUD<T> : IBaseCRUD<T> where T : class
        {
            FinaEstampaBase loja = new FinaEstampaBase();
    
            #region IBaseCRUD<T> Members
    
            public void Add(T pEntity)
            {
                loja.AddObject(pEntity.GetType().Name, pEntity);
            }
    
            public void Delete(T pEntity)
            {
                loja.DeleteObject(pEntity);
            }
    
            public void Attach(T pEntity)
            {
                loja.AttachTo(pEntity.GetType().Name, pEntity);
            }
    
            public void Detach(T pEntity)
            {
                loja.Detach(pEntity);
            }
    
            public void Update(T pEntity)
            {
                loja.ApplyCurrentValues<T>(pEntity.GetType().Name, pEntity);
            }
    
            public IQueryable<T> Find(Expression<Func<T, bool>> where)
            {
                return loja.CreateObjectSet<T>().Where(where);
            }
    
            public IQueryable<T> GetAll()
            {
                return loja.CreateObjectSet<T>();
            }
    
            public void SaveChanges()
            {
                loja.SaveChanges();
            }
    
            #endregion
        }

    Agora, olhe a diferença de código:

       public DataTable popularGridProduto(int idProduto)
            {
                string SQL = @"SELECT * FROM PRODUTO WHERE IDT_PRODUTO = @valor";
                conexao = new MySqlConnection(string_conexao);
                MySqlCommand cmd = new MySqlCommand(SQL, conexao);
                cmd.Parameters.AddWithValue("@valor", idProduto);
                MySqlDataAdapter da = new MySqlDataAdapter();
    
                da.SelectCommand = cmd;
                DataTable dt = new DataTable();
                da.Fill(dt);
                return dt;
    
            }
    
    
    LIST <T>: 
    
            public PRODUTO BuscarProduto(int idProduto)
            {
                return Find(p => p.IDT_PRODUTO.Equals(idProduto)).First();
            }

    Espero ter ajudado, um abraço!


    terça-feira, 5 de março de 2013 17:17
  • Boa tarde pessoal!

    Não esqueçam de marcar as respostas como corretas (se assim elas tiverem). Dessa forma, a próxima pessoa com dúvida terá mais facilidade de resolver seu problema, e ainda incentiva outros a responderem!

    Abraço!

    Felipo Gonçalves
    Microsoft Contingent Staff

    terça-feira, 5 de março de 2013 17:52
  • Olá, Vinicius Vendramel..!

    Agradeço desde já, e já me abriu muitas portas desde o seu exemplo.!

    Mas, Explique pra mim ..!

    o que é esse "T", qual seu significado na lista generica..?

    Ex.. seu...!

    public interface IBaseCRUD<T>

    e depois

    Ex.. seu..!

    public class AbstractCRUD<T> : IBaseCRUD<T> where T : class

    agora a Classe que herda da mesma tbm tem que ter o "T"..?

    e depois esse "Where T : Class".. o que significa esta expressao...?

    Atenciosamente

    André

    terça-feira, 5 de março de 2013 20:38
  • Isso é genérics amigo. 

    A ideia é escrever códigos genéricos, que funcionem para vários tipos de objetos sem precisar replicar o código. 
    Como você sabe, o c# é fortemente tipado, ou seja, se houver uma lógica que pode ser aplicada a várias classes, você teria que escrever essa classe várias vezes mudando apenas o TIPO de dados.

    Com generics você contorna isso, criando códigos para tipos que serão definidos no momento que for instanciar ou herdar uma classe. 

    public interface IBaseCRUD<T>

    O T é um apelido que você da ao tipo que você definir que será o T, pode ser qualquer nome, 
    ex:

     public interface IBaseCRUD<MeuTipo> 

    para utilizar essa interface, você precisa definir um tipo de dados para o tipo generico "<T>":

    ex: 
    Public class teste: IBaseCRUD<Model.Pessoa> // uma classe que implementa a interface.

    Nesse caso, todos os metodos definidos como "<T>" na interface irão se transformar em "Model.Pessoa".

    Um exemplo funcional para isso é a lista generica do .net LIST<T>.
    O que essa lista faz? simplesmente cria um arrayList tipado com o tipo definido em T.

    Ou seja, pra fazer uma lista tipada sem o generic "<T>", você teria que criar uma classe para cada tipo de dados do .net... ou seja stringList, intList, booleanList, etc... 
    E essas listar terão a mesma implementação no seu interior... ou seja, replicará o código dezenas de vezes... 

    Agora com generics, você cria a lógica que funciona em qualquer tipo de dados, simplesmente não definindo um Tipo de dados mas sim permitindo que você passe o tipo de dados que a lista receberá:

    ex: List<String>, List<Int>, List<bool>, List<Model.Pessoa> etc...

    O "WHERE" serve para definir regras de tipagem... exemplo em portugues:

    Você quer somente tipos de dados que implementem uma interface.
    Você quer criar uma logíca para seus objetos que utilizem uma classe base.
    Você precisa ter acesso a algumas propriedades do objeto.

    O mais importante, acredito que seja ter acesso a propriedades... como assim? 

    quando você define o "<T>" você não sabe que tipo de dados será definido a ele... ou seja... se tiver uma classe base com propriedades que você precisa utilizar na sua classe generica... você precisa dizer com o WHERE que sua classe "<T>" herda de PessoaBase... nesse caso, quando você fizer:

    public class Pessoa<T> where T:PessoaBase

    voce poderá acessar as propriedades da pessoa Base, ex:

    public class Pessoa<T> where T:PessoaBase
    {

    public void teste<T>(T pessoa)
    {
        int idPessoa = pessoa.IdPessoa; // dizendo que o T é uma pessoa base, você pode fazer isso.

    //etc...

    }
    }

    para curiosidade... se quiser retornar um tipo de dados padrão nos seus métodos utlizando generic... como exemplo, não encontrou nada e você não pode retornar null porque não se sabe se o tipo será um reference type (objeto) ou value type(string, int etc)... 
    você pode fazer:

    return default(T); 

    se T for um objeto retornará null
    se T for um value type, retornará o tipo padrão: ex: int =0; string = null ou emptystring; bool = false; datetime = datetime.MinValue, etc...



    Desenvolvedor de sistemas VB6, ASP, ASP.NET, C#, VB.NET, SQL Server, Oracle e MySql.


    quarta-feira, 6 de março de 2013 00:17
  • Boa noite Vinicius Vendramel ..!

    Agora ficou bem claro o conceito de genericos com a utilização de "<T>"  e "Where"..!

    Muitissimo obrigado pela atenção..!

    Atenciosamente

    André

    quarta-feira, 6 de março de 2013 00:43