泛型可以让你在类型上参数化代码,就像参数让你在值上参数化它一样。这可能并不能解释很多,所以让我们一步一步来:
假设您想要一个程序打印“我喜欢兔子”。你这样写:
static void Main()
{
ILikeBunnies();
}
void ILikeBunnies() { Console.WriteLine("I like bunnies"); }
一切顺利。但你也喜欢奶酪,所以现在你有:
static void Main()
{
ILikeBunnies();
ILikeCheese();
}
void ILikeBunnies() { Console.WriteLine("I like bunnies"); }
void ILikeCheese() { Console.WriteLine("I like cheese"); }
您注意到您的两个功能几乎相同。您想重用 same 功能,但为您喜欢的内容提供不同的值:
static void Main()
{
ILike("bunnies");
ILike("cheese");
}
void ILike(string what) { Console.WriteLine("I like " + what); }
这就是函数参数的用途:它们让您可以使用不同的值重用相同的代码。
泛型就是这样,但不是传入不同的值,而是传入 types。假设您的代码需要将两个字符串捆绑到一个数组中:
static void Main()
{
string[] s = Pair("a", "b");
}
string[] Pair(string a, string b) { return new string[] { a, b }; }
很好,花花公子。后来你意识到你还需要将整数捆绑到一个数组中:
static void Main()
{
string[] s = Pair("a", "b");
int[] i = Pair(1, 2);
}
string[] Pair(string a, string b) { return new string[] { a, b }; }
int[] Pair(int a, int b) { return new int[] { a, b }; }
就像以前一样,我们可以看到那里有一堆冗余。我们需要的是一个返回一对 whatever 的函数以及一个传入我们想要一对的类型的方法。这就是泛型的用途:
static void Main()
{
string[] s = Pair<string>("a", "b");
int[] i = Pair<int>(1, 2);
}
T[] Pair<T>(T a, T b) { return new T[] { a, b }; }
尖括号可以让你将类型传递给函数,就像括号让你传递值一样。这里的“T”是类型参数的名称,就像上面的值参数“what”一样。函数中出现的任何位置 T 都将替换为您传入的实际类型(示例中为 string 和 int)。
除此之外,你可以用泛型做很多事情,但这是基本思想:泛型让你可以将类型传递给函数(和类),就像参数让你传递值一样。