C# 中的泛型是什么?
作者:互联网
C# 中的泛型是什么?
很难在不遇到泛型的情况下在 dotnet 中进行大量开发。毕竟,自 2000 年代初的 .NET Framework 2.0 以来,我们已经有了 和 .但是 C# 中的泛型到底是什么?List<T>Dictionary<TKey, TValue>
在本文中,我们将探讨 C# 中的泛型是什么,它们是如何工作的,我们如何在 .NET 代码中利用它们,以及在 C# 中实现你自己的泛型类型和泛型方法如何帮助提高你的编码能力。
C# 中的泛型是什么?
泛型是一项 dotnet 语言功能,旨在减少我们作为开发人员可能需要执行的复制和粘贴量,以提供可应用于任何需要它的 dotnet 类型的通用功能。
C# 泛型之前的世界
例如,假设您需要创建一个方法,该方法接收整数列表并返回仅包含列表的第一个元素和最后一个元素的数组(假设列表不会为 null,并且其中至少包含一个元素)。
其代码如下所示:
public int[] BuildFirstLastArray(List<int> input)
{
int[] result = new int[2]();
// For ease of readability, let's just use LINQ here
result[0] = input.First();
result[1] = input.Last();
return result;
}
诚然,这是一组任意的要求和一些相当简单的代码。
假设我们原来的方法满足了我们的需求,但现在我们得到了一个新的要求,说我们需要能够返回字符串列表中第一个和最后一个元素的数组。
我们的代码非常类似于上面的整数列表的代码:
public string[] BuildFirstLastArray(List<string> input)
{
string[] result = new string[2]();
// For ease of readability, let's just use LINQ here
result[0] = input.First();
result[1] = input.Last();
return result;
}
如果你和我一样,你现在可能会开始怀疑是否有更好的方法。毕竟,您的代码可能不像此示例问题那么微不足道,而且我们都已经以艰难的方式了解到重复是不好的。
正如您对本文主题所期望的那样,泛型可以帮助解决此问题。
在 C 中声明泛型方法
使用 C# 泛型,我们可以创建一个方法,该方法有效地充当我们上面明确声明的方法的模板。
这是一个复杂的句子,所以让我们进入一个例子。
在我们前面的代码中,这两种方法之间的唯一区别是其中一个方法使用 int 值,另一个方法处理字符串值。
我们可以改为在代码中使用占位符或泛型类型来表示稍后将提供的类型,而不是为每个类型声明我们想要支持的新方法。
为此,我们在方法名称之后和带有参数声明的括号之前使用尖括号 ('s),如下所示:<>
public T[] BuildFirstLastArray<T>(List<T> input)
{
T[] result = new T[2]();
// For ease of readability, let's just use LINQ here
result[0] = input.First();
result[1] = input.Last();
return result;
}
诚然,如果没有显式类型声明和在参数列表之前添加的代码,上面的代码看起来更奇怪,但这个泛型方法现在可以处理对字符串、整数、双精度或各种其他类型的列表的调用。<T>
在 C 中调用泛型方法
我们通过告诉 C# 编译器我们希望为泛型类型参数提供什么值来调用泛型方法。
对于上面的示例,我们可以调用 s 和 s,如下所示:BuildFirstLastArrayintstring
List<int> numbers = new() { 1, 2, 3};
int[] intResults = BuildFirstLastArray<int>(numbers);
List<string> names = new() { "Priya", "Mohammed", "Alexis" };
string[] strResults = BuildFirstLastArray<string>(names);
请注意,在上面的代码中,我们如何为上述方法提供泛型类型参数。当此代码运行时,int 或字符串值将替换为泛型方法中的 T 占位符。<int><string>
也可以有一个接受多个泛型类型参数的方法。我们可以通过添加逗号,然后在尖括号内添加后续类型参数来支持这一点,如下所示:
public string CombineTypes<T1, T2>(T1 firstType, T2 secondType)
{
// Implementation omitted...
}
这里我们有一个可以用任意两种类型(包括同一类型两次)调用的方法。这些类型参数将在方法内部使用,并分别称为 T1 和 T2。CombineTypes
注意:不必调用泛型类型参数 T、T1 或 T2,但在提供单个类型参数时通常约定使用 T。当提供多个类型参数时,通常最好使用一组有意义的名称,例如 TKey 和 TValue,但如果这是不可能的,T1、T2 等仍然可以帮助澄清用法。
C# 编译器对泛型的作用
这些类型参数会导致 C# 在每次编译器遇到不同的类型参数组合时为指定的 Type 参数自动生成方法。
手动创建所有这些具有不同类型的重载方法与使用泛型之间的主要区别在于,如果我们使用 C# 泛型,则无需重复代码。这使我们能够在一个地方轻松添加新功能、文档或修复代码问题,并使该更改对该通用方法的任何版本有效。
C 语言中的泛型类
我们已经了解了如何创建泛型方法,但有时您希望整个泛型类都以泛型类型为中心。 就是一个很好的例子。泛型列表管理特定类型的项的有序集合,并提供用于与该集合交互的强类型方法和属性。List<T>
让我们看一下如何在 C# 中声明和使用自己的泛型类。
很难在不遇到泛型的情况下在 dotnet 中进行大量开发。毕竟,自 2000 年代初的 .NET Framework 2.0 以来,我们已经有了 和 .但是 C# 中的泛型到底是什么?List<T>Dictionary<TKey, TValue>
在本文中,我们将探讨 C# 中的泛型是什么,它们是如何工作的,我们如何在 .NET 代码中利用它们,以及在 C# 中实现你自己的泛型类型和泛型方法如何帮助提高你的编码能力。
C# 中的泛型是什么?
泛型是一项 dotnet 语言功能,旨在减少我们作为开发人员可能需要执行的复制和粘贴量,以提供可应用于任何需要它的 dotnet 类型的通用功能。
C# 泛型之前的世界
例如,假设您需要创建一个方法,该方法接收整数列表并返回仅包含列表的第一个元素和最后一个元素的数组(假设列表不会为 null,并且其中至少包含一个元素)。
其代码如下所示:
public int[] BuildFirstLastArray(List<int> input)
{
int[] result = new int[2]();
// For ease of readability, let's just use LINQ here
result[0] = input.First();
result[1] = input.Last();
return result;
}
诚然,这是一组任意的要求和一些相当简单的代码。
假设我们原来的方法满足了我们的需求,但现在我们得到了一个新的要求,说我们需要能够返回字符串列表中第一个和最后一个元素的数组。
我们的代码非常类似于上面的整数列表的代码:
public string[] BuildFirstLastArray(List<string> input)
{
string[] result = new string[2]();
// For ease of readability, let's just use LINQ here
result[0] = input.First();
result[1] = input.Last();
return result;
}
如果你和我一样,你现在可能会开始怀疑是否有更好的方法。毕竟,您的代码可能不像此示例问题那么微不足道,而且我们都已经以艰难的方式了解到重复是不好的。
正如您对本文主题所期望的那样,泛型可以帮助解决此问题。
在 C 中声明泛型方法
使用 C# 泛型,我们可以创建一个方法,该方法有效地充当我们上面明确声明的方法的模板。
这是一个复杂的句子,所以让我们进入一个例子。
在我们前面的代码中,这两种方法之间的唯一区别是其中一个方法使用 int 值,另一个方法处理字符串值。
我们可以改为在代码中使用占位符或泛型类型来表示稍后将提供的类型,而不是为每个类型声明我们想要支持的新方法。
为此,我们在方法名称之后和带有参数声明的括号之前使用尖括号 ('s),如下所示:<>
public T[] BuildFirstLastArray<T>(List<T> input)
{
T[] result = new T[2]();
// For ease of readability, let's just use LINQ here
result[0] = input.First();
result[1] = input.Last();
return result;
}
诚然,如果没有显式类型声明和在参数列表之前添加的代码,上面的代码看起来更奇怪,但这个泛型方法现在可以处理对字符串、整数、双精度或各种其他类型的列表的调用。<T>
在 C 中调用泛型方法
我们通过告诉 C# 编译器我们希望为泛型类型参数提供什么值来调用泛型方法。
对于上面的示例,我们可以调用 s 和 s,如下所示:BuildFirstLastArrayintstring
List<int> numbers = new() { 1, 2, 3};
int[] intResults = BuildFirstLastArray<int>(numbers);
List<string> names = new() { "Priya", "Mohammed", "Alexis" };
string[] strResults = BuildFirstLastArray<string>(names);
请注意,在上面的代码中,我们如何为上述方法提供泛型类型参数。当此代码运行时,int 或字符串值将替换为泛型方法中的 T 占位符。<int><string>
也可以有一个接受多个泛型类型参数的方法。我们可以通过添加逗号,然后在尖括号内添加后续类型参数来支持这一点,如下所示:
public string CombineTypes<T1, T2>(T1 firstType, T2 secondType)
{
// Implementation omitted...
}
这里我们有一个可以用任意两种类型(包括同一类型两次)调用的方法。这些类型参数将在方法内部使用,并分别称为 T1 和 T2。CombineTypes
注意:不必调用泛型类型参数 T、T1 或 T2,但在提供单个类型参数时通常约定使用 T。当提供多个类型参数时,通常最好使用一组有意义的名称,例如 TKey 和 TValue,但如果这是不可能的,T1、T2 等仍然可以帮助澄清用法。
C# 编译器对泛型的作用
这些类型参数会导致 C# 在每次编译器遇到不同的类型参数组合时为指定的 Type 参数自动生成方法。
手动创建所有这些具有不同类型的重载方法与使用泛型之间的主要区别在于,如果我们使用 C# 泛型,则无需重复代码。这使我们能够在一个地方轻松添加新功能、文档或修复代码问题,并使该更改对该通用方法的任何版本有效。
C 语言中的泛型类
我们已经了解了如何创建泛型方法,但有时您希望整个泛型类都以泛型类型为中心。 就是一个很好的例子。泛型列表管理特定类型的项的有序集合,并提供用于与该集合交互的强类型方法和属性。List<T>
让我们看一下如何在 C# 中声明和使用自己的泛型类。