C#基础篇(11)泛型类与泛型方法详解

发布于:2025-07-13 ⋅ 阅读:(15) ⋅ 点赞:(0)

一、C# 中的泛型类详解

泛型类是 C# 中一种强大的特性,它允许你定义可以使用不同类型的类,而无需为每种类型编写单独的类。泛型类通过类型参数实现这一功能,提高了代码的重用性、类型安全性性能

1. 泛型类的基本语法

public class GenericClass<T>
{
    // T 是类型参数,可以在类中作为类型使用
    private T data;
    
    public GenericClass(T value)
    {
        data = value;
    }
    
    public T GetData()
    {
        return data;
    }
}

2. 泛型类的使用

// 使用int类型实例化泛型类
GenericClass<int> intGeneric = new GenericClass<int>(10);
int intValue = intGeneric.GetData();

// 使用string类型实例化泛型类
GenericClass<string> stringGeneric = new GenericClass<string>("Hello");
string stringValue = stringGeneric.GetData();

3. 泛型类的优势

  1. 类型安全​:编译时检查类型,避免运行时类型转换错误
  2. 代码重用​:一套代码可以用于多种数据类型
  3. 性能优化​:避免了装箱和拆箱操作(对于值类型)
  4. 减少强制转换​:代码更简洁,不需要频繁的类型转换

4. 多类型参数的泛型类

泛型类可以有多个类型参数:

public class Pair<TKey, TValue>
{
    public TKey Key { get; set; }
    public TValue Value { get; set; }
    
    public Pair(TKey key, TValue value)
    {
        Key = key;
        Value = value;
    }
}

// 使用示例
var pair = new Pair<int, string>(1, "One");

5. 泛型约束

可以为类型参数添加约束,限制可以使用的类型:

约束类型 语法 描述
类约束 where T : class T必须是引用类型
结构约束 where T : struct T必须是值类型(Nullable除外)
基类约束 where T : BaseClass T必须继承自BaseClass
接口约束 where T : IInterface T必须实现IInterface
无参数构造函数约束 where T : new() T必须有无参构造函数
裸类型约束 where T : U T必须继承自或实现U

示例:

public class GenericClass<T> where T : IComparable, new()
{
    private T data;
    
    public GenericClass()
    {
        data = new T(); // 需要new()约束
    }
    
    public int CompareTo(T other)
    {
        return data.CompareTo(other); // 需要IComparable约束
    }
}

6. 泛型类的继承

泛型类可以继承自其他泛型或非泛型类:

public class BaseClass<T>
{
    // 基类实现
}

// 派生类可以是具体类型
public class DerivedClass : BaseClass<int>
{
    // 实现
}

// 派生类也可以是泛型类
public class DerivedGenericClass<T> : BaseClass<T>
{
    // 实现
}

// 派生类可以添加自己的类型参数
public class DerivedMultiClass<T, U> : BaseClass<T>
{
    // 实现
}

7. 静态成员

泛型类的静态成员是针对每个封闭类型独立的:

public class GenericClass<T>
{
    public static int Count { get; set; }
}

// 使用示例
GenericClass<int>.Count = 10;
GenericClass<string>.Count = 20;

Console.WriteLine(GenericClass<int>.Count); // 输出10
Console.WriteLine(GenericClass<string>.Count); // 输出20

8. 泛型类与反射

可以使用反射获取泛型类型信息:

Type genericType = typeof(List<>);
Type constructedType = genericType.MakeGenericType(typeof(int));
object list = Activator.CreateInstance(constructedType);

总结

C# 泛型类是一种强大的语言特性,它通过类型参数化实现了代码的高度重用,同时保持了类型安全和性能。合理使用泛型类可以:

  • 减少代码重复
  • 提高类型安全性
  • 改善性能(特别是对于值类型)
  • 创建更灵活、更通用的数据结构

在设计泛型类时,应当考虑类型约束、命名规范、文档注释等因素,以确保代码的可读性和可维护性。

二、C# 中的泛型方法详解

泛型方法是 C# 泛型编程的核心组成部分,它允许你定义可以操作多种类型的方法,而无需为每种类型编写单独的方法。泛型方法提供了类型安全代码重用的双重优势。

1. 泛型方法的基本语法

// 泛型方法定义
public T GenericMethod<T>(T parameter)
{
    // 方法体
    return parameter;
}

// 使用示例
int result = GenericMethod<int>(5); // 显式指定类型
string text = GenericMethod("Hello"); // 类型推断

核心特点:

  1. 类型参数​:使用尖括号<T>声明类型参数
  2. 类型安全​:编译时类型检查
  3. 代码重用​:同一方法可用于多种类型
  4. 性能优势​:避免值类型的装箱拆箱操作

2. 泛型方法的定义方式

1. 普通类中的泛型方法

public class Utility
{
    public void Print<T>(T value)
    {
        Console.WriteLine($"Type: {typeof(T)}, Value: {value}");
    }
    
    // 多类型参数
    public TResult Convert<TInput, TResult>(TInput input)
    {
        return (TResult)Convert.ChangeType(input, typeof(TResult));
    }
}

2. 泛型类中的泛型方法

public class Repository<TEntity>
{
    // 类类型参数TEntity与方法类型参数T是独立的
    public T Execute<T>(Func<TEntity, T> selector)
    {
        // 实现...
    }
}

3. 静态类中的泛型方法

public static class MathUtils
{
    public static T Max<T>(T a, T b) where T : IComparable<T>
    {
        return a.CompareTo(b) > 0 ? a : b;
    }
}

4. 接口中的泛型方法

public interface IProcessor
{
    TResult Process<TInput, TResult>(TInput input);
}

3. 泛型方法的类型参数约束

约束可以限制可用于泛型方法的类型参数,提供更强的类型安全和功能支持。

常用约束类型

约束类型 语法示例 说明
类约束 where T : class T必须是引用类型
结构约束 where T : struct T必须是值类型(Nullable除外)
基类约束 where T : BaseClass T必须继承自BaseClass
接口约束 where T : IInterface T必须实现IInterface
无参构造函数约束 where T : new() T必须有无参构造函数
裸类型约束 where T : U T必须继承自或实现U

约束组合示例

public T CreateAndCompare<T>(T value) where T : class, IComparable<T>, new()
{
    T newInstance = new T();
    return value.CompareTo(newInstance) > 0 ? value : newInstance;
}

4. 泛型方法的高级特性

1. 类型推断

C#编译器通常可以推断泛型方法的类型参数,无需显式指定:

// 不需要指定<int>,编译器从参数推断
int max = MathUtils.Max(5, 10); 

2. 泛型方法与重载

泛型方法可以与非泛型方法重载:

public class Printer
{
    public void Print<T>(T value) { /* 泛型实现 */ }
    public void Print(int value) { /* 特定类型实现 */ }
}

调用时,编译器会优先选择最具体的匹配。

3. 递归泛型方法

泛型方法可以递归调用自身:

public static T[] BubbleSort<T>(T[] array) where T : IComparable<T>
{
    for (int i = 0; i < array.Length - 1; i++)
    {
        if (array[i].CompareTo(array[i + 1]) > 0)
        {
            T temp = array[i];
            array[i] = array[i + 1];
            array[i + 1] = temp;
            return BubbleSort(array); // 递归调用
        }
    }
    return array;
}

4. 协变和逆变(C# 4.0+)

使用inout修饰符:

// 协变返回类型
public interface IFactory<out T>
{
    T Create();
}

// 逆变参数
public interface IComparer<in T>
{
    int Compare(T x, T y);
}

5. 泛型方法与反射

可以通过反射调用泛型方法:

public class ReflectionExample
{
    public static void CallGenericMethod()
    {
        var method = typeof(Utility).GetMethod("Print");
        var genericMethod = method.MakeGenericMethod(typeof(int));
        genericMethod.Invoke(null, new object[] { 42 });
    }
}

总结

C# 泛型方法是强大的编程工具,它:

  1. 提高了代码的重用性类型安全
  2. 消除了强制转换的需要
  3. 为值类型提供了更好的性能
  4. 使API设计更加灵活表达力强

合理使用泛型方法可以显著提高代码质量,但也要注意避免过度复杂化。掌握泛型方法的使用是成为高级C#开发者的重要一步。


网站公告

今日签到

点亮在社区的每一天
去签到