C # - typy generyczne
Genericspozwalają zdefiniować specyfikację typu danych elementów programowania w klasie lub metodzie, dopóki nie zostaną one faktycznie użyte w programie. Innymi słowy, typy ogólne umożliwiają napisanie klasy lub metody, która może działać z dowolnym typem danych.
Piszesz specyfikacje dla klasy lub metody, zastępując parametry dla typów danych. Gdy kompilator napotka konstruktora dla klasy lub wywołanie funkcji dla metody, generuje kod obsługujący określony typ danych. Prosty przykład pomógłby zrozumieć koncepcję -
using 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) {
//declaring an int array
MyGenericArray<int> intArray = new MyGenericArray<int>(5);
//setting values
for (int c = 0; c < 5; c++) {
intArray.setItem(c, c*5);
}
//retrieving the values
for (int c = 0; c < 5; c++) {
Console.Write(intArray.getItem(c) + " ");
}
Console.WriteLine();
//declaring a character array
MyGenericArray<char> charArray = new MyGenericArray<char>(5);
//setting values
for (int c = 0; c < 5; c++) {
charArray.setItem(c, (char)(c+97));
}
//retrieving the values
for (int c = 0; c< 5; c++) {
Console.Write(charArray.getItem(c) + " ");
}
Console.WriteLine();
Console.ReadKey();
}
}
}
Kiedy powyższy kod jest kompilowany i wykonywany, daje następujący wynik -
0 5 10 15 20
a b c d e
Funkcje typów generycznych
Generics to technika, która wzbogaca Twoje programy w następujący sposób -
Pomaga zmaksymalizować ponowne wykorzystanie kodu, bezpieczeństwo typów i wydajność.
Możesz tworzyć ogólne klasy kolekcji. Biblioteka klas .NET Framework zawiera kilka nowych klas kolekcji ogólnych w przestrzeni nazw System.Collections.Generic . Możesz użyć tych ogólnych klas kolekcji zamiast klas kolekcji w przestrzeni nazw System.Collections .
Możesz tworzyć własne ogólne interfejsy, klasy, metody, zdarzenia i delegatów.
Możesz tworzyć klasy ogólne ograniczone, aby umożliwić dostęp do metod na określonych typach danych.
Możesz uzyskać informacje o typach używanych w ogólnym typie danych w czasie wykonywania za pomocą refleksji.
Metody ogólne
W poprzednim przykładzie użyliśmy klasy ogólnej; możemy zadeklarować metodę ogólną z parametrem typu. Poniższy program ilustruje koncepcję -
using 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';
//display values before swap:
Console.WriteLine("Int values before calling swap:");
Console.WriteLine("a = {0}, b = {1}", a, b);
Console.WriteLine("Char values before calling swap:");
Console.WriteLine("c = {0}, d = {1}", c, d);
//call swap
Swap<int>(ref a, ref b);
Swap<char>(ref c, ref d);
//display values after swap:
Console.WriteLine("Int values after calling swap:");
Console.WriteLine("a = {0}, b = {1}", a, b);
Console.WriteLine("Char values after calling swap:");
Console.WriteLine("c = {0}, d = {1}", c, d);
Console.ReadKey();
}
}
}
Kiedy powyższy kod jest kompilowany i wykonywany, daje następujący wynik -
Int values before calling swap:
a = 10, b = 20
Char values before calling swap:
c = I, d = V
Int values after calling swap:
a = 20, b = 10
Char values after calling swap:
c = V, d = I
Delegaci ogólni
Możesz zdefiniować delegata ogólnego z parametrami typu. Na przykład -
delegate T NumberChanger<T>(T n);
Poniższy przykład pokazuje użycie tego delegata -
using 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) {
//create delegate instances
NumberChanger<int> nc1 = new NumberChanger<int>(AddNum);
NumberChanger<int> nc2 = new NumberChanger<int>(MultNum);
//calling the methods using the delegate objects
nc1(25);
Console.WriteLine("Value of Num: {0}", getNum());
nc2(5);
Console.WriteLine("Value of Num: {0}", getNum());
Console.ReadKey();
}
}
}
Kiedy powyższy kod jest kompilowany i wykonywany, daje następujący wynik -
Value of Num: 35
Value of Num: 175