泛型
泛型是一种编程语言特性,它可以让我们编写更加通用、可重用的代码。通过泛型,我们可以定义一些类、接口或方法,这些类、接口或方法可以接受任意类型的参数,而不需要预先指定具体的类型。
在C#中,泛型最常用的场景是定义集合类。比如,List<T>、Dictionary<TKey, TValue>、Queue<T>和Stack<T>等都是泛型类。
使用泛型可以让我们编写更加灵活、可靠的代码,避免出现因类型转换错误等原因导致的程序运行异常。同时,泛型还可以提高程序的性能,因为它可以减少装箱和拆箱等操作,提高程序的效率。
以下是一个使用泛型的简单示例,该示例演示了如何使用泛型创建一个动态数组并向其中添加元素:
using System;
using System.Collections.Generic;
class Program
{
static void Main(string[] args)
{
List<int> list = new List<int>(); // 创建一个 List<int> 类型的对象
list.Add(1); // 向 list 中添加一个整数值 1
list.Add(2); // 向 list 中添加一个整数值 2
list.Add(3); // 向 list 中添加一个整数值 3
foreach (int num in list)
{
Console.WriteLine(num); // 输出 list 中的每个整数值
}
}
}
泛型类
泛型类是一种可以具有类型参数的类,它可以通过指定类型参数来创建不同类型的实例。在 C# 中,使用尖括号(<>)指定泛型参数,可以将任何类型指定为参数类型。
下面是一个简单的泛型类的示例:
public class GenericClass<T>
{
private T _value;
public GenericClass(T value)
{
_value = value;
}
public T GetValue()
{
return _value;
}
}
这个泛型类包含一个类型参数 T,表示这个类可以使用任何类型作为参数。它有一个构造函数,接受一个类型为 T 的参数,并将其存储在私有变量 _value 中。GetValue 方法返回 _value 变量的值。
可以使用该类创建不同类型的实例。例如,可以创建一个 GenericClass<string> 类型的实例来存储字符串值,也可以创建一个 GenericClass<int> 类型的实例来存储整数值。
下面是使用 GenericClass 类的示例:
GenericClass<string> stringClass = new GenericClass<string>("Hello, world!");
Console.WriteLine(stringClass.GetValue()); // 输出 "Hello, world!"
GenericClass<int> intClass = new GenericClass<int>(42);
Console.WriteLine(intClass.GetValue()); // 输出 "42"
泛型约束
泛型约束(Generic Constraints)是指通过限制泛型类型参数的类型,来保证代码的正确性和可读性。在使用泛型类型参数的时候,我们有时需要对泛型类型参数进行一些限制,以保证类型参数能够正确地被使用。泛型约束提供了一种强制要求泛型类型参数满足某些条件的机制。
C#中泛型约束的语法格式为where T : constraint,其中 T 为泛型类型参数,constraint 为限制条件。可以使用多个约束,通过逗号分隔。泛型约束可以分为以下几类:
where T : class 表示 T 必须是引用类型,也可以是 null。
where T : struct 表示 T 必须是值类型,除了 Nullable<T>。
where T : new() 表示 T 必须有无参的公共构造函数。
where T : <base class name> 表示 T 必须是指定的基类或派生自指定的基类。
where T : <interface name> 表示 T 必须实现指定的接口。
where T : U 表示 T 必须派生自 U。
下面是一个使用泛型约束的例子,限制泛型类型参数 T 必须是实现了 IComparable 接口的类型:
public class MyClass<T> where T : IComparable
{
public T Max(T a, T b)
{
return a.CompareTo(b) > 0 ? a : b;
}
}
在上面的例子中,使用了泛型类型参数 T 来表示参数 a 和 b 的类型。由于在 Max 方法中调用了 CompareTo 方法,因此必须对 T 进行约束,要求它实现了 IComparable 接口。这样,才能保证 a 和 b 的类型具有可比性,从而得到最大值。
在使用泛型约束时,需要注意以下几点:
泛型约束只能在类、接口、委托和方法中使用。
泛型约束不能继承,也不能被其他类型继承。
多个约束可以组合使用,通过逗号分隔。
对泛型类型参数的约束只是一种限制,实际上并不会改变泛型类型参数的类型。