Generics em C# Explicados: Código Flexível e Type-Safe para Qualquer Tipo de Dado
Generics permitem definir a especificação do tipo de dados de elementos de programação em uma classe ou método, até que seja realmente usado no programa. Em outras palavras, generics permitem escrever uma classe ou método que pode funcionar com qualquer tipo de dado.
Você escreve as especificações para a classe ou método, com parâmetros substitutos para tipos de dados. Quando o compilador encontra um construtor para a classe ou uma chamada de função para o método, ele gera código para lidar com o tipo de dado específico. Um exemplo simples ajudará a entender o conceito:
Demo ao Vivousing System;
using System.Collections.Generic;
namespace GenericApplication {
public class MyGenericArray<T> {
private T[] array;
public MyGenericArray(int size) {
array = new T[size + 1];
}
public T getItem(int index) {
return array[index];
}
public void setItem(int index, T value) {
array[index] = value;
}
}
class Tester {
static void Main(string[] args) {
//declarando um array int
MyGenericArray<int> intArray = new MyGenericArray<int>(5);
//definindo valores
for (int c = 0; c < 5; c++) {
intArray.setItem(c, c*5);
}
//recuperando os valores
for (int c = 0; c < 5; c++) {
Console.Write(intArray.getItem(c) + " ");
}
Console.WriteLine();
//declarando um array de caracteres
MyGenericArray<char> charArray = new MyGenericArray<char>(5);
//definindo valores
for (int c = 0; c < 5; c++) {
charArray.setItem(c, (char)(c+97));
}
//recuperando os valores
for (int c = 0; c< 5; c++) {
Console.Write(charArray.getItem(c) + " ");
}
Console.WriteLine();
Console.ReadKey();
}
}
}
Quando o código acima é compilado e executado, produz o seguinte resultado:
0 5 10 15 20 a b c d e
Características dos Generics
Generics é uma técnica que enriquece seus programas das seguintes formas:
Ajuda a maximizar reutilização de código, type safety e performance.
Você pode criar classes de coleção genéricas. A biblioteca de classes do .NET Framework contém várias novas classes de coleção genéricas no namespace System.Collections.Generic. Você pode usar essas classes de coleção genéricas em vez das classes de coleção no namespace System.Collections.
Você pode criar suas próprias interfaces genéricas, classes, métodos, eventos e delegates.
Você pode criar classes genéricas restritas para permitir acesso a métodos em tipos de dados específicos.
Você pode obter informações sobre os tipos usados em um tipo de dado genérico em tempo de execução por meio de reflection.
Métodos Genéricos
No exemplo anterior, usamos uma classe genérica; podemos declarar um método genérico com um parâmetro de tipo. O programa a seguir ilustra o conceito:
Demo ao Vivousing System;
using System.Collections.Generic;
namespace GenericMethodAppl {
class Program {
static void Swap<T>(ref T lhs, ref T rhs) {
T temp;
temp = lhs;
lhs = rhs;
rhs = temp;
}
static void Main(string[] args) {
int a, b;
char c, d;
a = 10;
b = 20;
c = 'I';
d = 'V';
//exibe valores antes do swap:
Console.WriteLine("Valores int antes de chamar swap:");
Console.WriteLine("a = {0}, b = {1}", a, b);
Console.WriteLine("Valores char antes de chamar swap:");
Console.WriteLine("c = {0}, d = {1}", c, d);
//chama swap
Swap<int>(ref a, ref b);
Swap<char>(ref c, ref d);
//exibe valores após swap:
Console.WriteLine("Valores int após chamar swap:");
Console.WriteLine("a = {0}, b = {1}", a, b);
Console.WriteLine("Valores char após chamar swap:");
Console.WriteLine("c = {0}, d = {1}", c, d);
Console.ReadKey();
}
}
}
Quando o código acima é compilado e executado, produz o seguinte resultado:
Valores int antes de chamar swap: a = 10, b = 20 Valores char antes de chamar swap: c = I, d = V Valores int após chamar swap: a = 20, b = 10 Valores char após chamar swap: c = V, d = I
Delegates Genéricos
Você pode definir um delegate genérico com parâmetros de tipo. Por exemplo:
delegate T NumberChanger<T>(T n);
O exemplo a seguir mostra o uso deste delegate:
Demo ao Vivousing System;
using System.Collections.Generic;
delegate T NumberChanger<T>(T n);
namespace GenericDelegateAppl {
class TestDelegate {
static int num = 10;
public static int AddNum(int p) {
num += p;
return num;
}
public static int MultNum(int q) {
num *= q;
return num;
}
public static int getNum() {
return num;
}
static void Main(string[] args) {
//cria instâncias do delegate
NumberChanger<int> nc1 = new NumberChanger<int>(AddNum);
NumberChanger<int> nc2 = new NumberChanger<int>(MultNum);
//chamando os métodos usando os objetos delegate
nc1(25);
Console.WriteLine("Valor de Num: {0}", getNum());
nc2(5);
Console.WriteLine("Valor de Num: {0}", getNum());
Console.ReadKey();
}
}
}
Quando o código acima é compilado e executado, produz o seguinte resultado:
Valor de Num: 35 Valor de Num: 175
Linguagem C
- C# Hello World – Criando Sua Primeira Aplicação C#
- Entendendo Palavras-chave e Identificadores em C#: Regras, Listas e Boas Práticas
- Domine Variáveis e Tipos de Dados Primitivos em C#: Guia Completo
- Operadores em C# – Guia Completo dos Operadores em C#
- Dominando Operadores Bitwise e Bit Shift em C#: Guia Abrangente
- Fundamentos de C#: Essenciais de Entrada e Saída
- Expressões, Instruções e Blocos em C#: Guia Completo com Exemplos Práticos
- Dominando Comentários em C#: Tipos, Boas Práticas e Documentação XML
- Dominando a Instrução Switch em C#: Sintaxe, Exemplos e Boas Práticas
- Operador Ternário em C#: Guia Conciso para Expressões Condicionais