C#-13 泛型

本文详细介绍了C#中的泛型概念,包括泛型的用途、泛型类的声明与实例化、泛型方法的定义与调用、泛型结构、泛型委托以及泛型接口的使用。通过示例代码展示了如何在实际编程中应用泛型,强调了泛型在代码复用和类型安全性方面的优势。同时,文章还提到了泛型的约束条件,如类型参数必须是值类型或引用类型,以及必须具有无参数构造函数等。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一 泛型

泛型提供了一种更优雅的方式,可以让多个类型共享一组代码。泛型允许我们声明类型参数化的代码,可以用不同的类型进行实例化。

也就是说,我们可以用"类型占位符"来写代码,然后在创建类的实例时指明真实的类型。

C#提供了5种泛型:类、结构、接口、委托和方法。

二 泛型类

如下代码声明了一个SomeClass的泛型类,类型参数T1和T2列在尖括号中,当作真实类型在声明的主体中使用。

class Program
{
    static void Main(string[] args)
    {
        //使用泛型类声明对象,提供short、int类型实参。
        SomeClass<short, int> s1Class = new SomeClass<short, int>();

        SomeClass<int, long> s2Class = new SomeClass<int, long>();
    }
}

class SomeClass<T1, T2> where T1 : new() where T2 : new()
{
    public T1 SomeVar = new T1();
    public T2 OtherVar = new T2();
}

where是对泛型添加的约束,where T :new() 表示 类型T必须具有无参数的公共构造函数。

以下为可添加的约束类型:

约束说明
T:struct类型参数必须是值类型。
T:class类型参数必须是引用类型;这一点也适用于任何类、接口、委托或数组类型。
T:new()类型参数必须具有无参数的公共构造函数。
T:<基类>类型参数必须是指定的基类或派生自指定的基类(非密封类)
T:<接口>类型参数必须是指定的接口或实现指定的接口。 可以指定多个接口约束。 约束接口也可以是泛型的。
T:U为 T 提供的类型参数必须是为 U 提供的参数或派生自为 U 提供的参数。

三 泛型方法

泛型方法具有类型参数列表和可选的约束。

//  <T1,T2> : 为泛型参数列表
//  (T1 t1, T2 t2) : 为方法参数列表
//  where T1 : Person : 为约束子句,表示T1类必须为Person类或其子类
public void PrintData<T1, T2>(T1 t1, T2 t2) where T1 : Person 
{
    ...
}

调用泛型方法,应该在方法调用时提供类型实参。

下列是泛型方法的使用实例:

static public void ReverseAndPrint<T>(T[] arr)
{
    Array.Reverse(arr);
    foreach (var item in arr)
    {
        Console.WriteLine(item);
    }
}

static void Main(string[] args)
{
    var intArr = new int[] { 1, 2, 3, 4, 5 };
    var strArr = new string[] { "a", "b", "c", "d", "e" };
    ReverseAndPrint<int>(intArr);       //调用泛型方法
    ReverseAndPrint(intArr);            //推断类型并调用
    ReverseAndPrint<string>(strArr);
    ReverseAndPrint(strArr);
}

四 泛型结构

与泛型类类似,泛型结构也可以有类型参数和约束。泛型结构的规则与条件与泛型类是一样的。

五 泛型委托

泛型委托和非泛型委托非常类似,不过类型参数决定了能接受什么样的方法。

//  <T, R> : 为类型参数
//  (T value) : 为委托形参
//  R : 返回类型
delegate R MyDelegate<T, R>(T value);

下面是一个泛型委托的示例:

delegate void MyDelegate<T>(T value);   //泛型委托
class Simple
{
    public static void PrintString(string s)
    {
        Console.WriteLine(s);
    }
    public static void PrintUpperString(string s)
    {
        Console.WriteLine(s.ToUpper());
    }
}

static void Main(string[] args)
{
    var myDel = new MyDelegate<string>(Simple.PrintString);
    myDel += Simple.PrintUpperString;
    myDel("hello world");
}

六 泛型接口

泛型接口允许我们编写参数和接口成员返回类型是泛型类型参数的接口。

下面是泛型接口的示例:

interface IMyIfc<T>
{
    T ReturnIt(T inValue);
}

class Simple : IMyIfc<int>, IMyIfc<string>
{
    public int ReturnIt(int inValue)
    {
        return inValue;
    }

    public string ReturnIt(string inValue)
    {
        return inValue;
    }
}

class Program
{
    static void Main(string[] args)
    {
        var sim = new Simple();
        Console.WriteLine(sim.ReturnIt(5));
        Console.WriteLine(sim.ReturnIt("hello world")) ;
    }
}
### C# 概述 C# 提供了一种机制,在定义方法、类、接口时不涉及具体的类,而是在使用时再指定实际的数据类。这不仅提高了代码的灵活性和重用性,还增强了类安全性并优化了性能[^1]。 #### 的优势 利用技术能够实现最大化的代码复用度、保持类安全性和提升执行效率。借助于.NET框架提供的`System.Collections.Generic`命名空间下的多个内置集合类,开发者可以直接采用这些高效且类安全的数据结构来代替旧版非版本[^2]。 #### 创建自定义组件 除了使用现成的集合外,还可以构建属于自己的接口、类、方法等。下面是一个简单的栈(Stack)实现例子: ```csharp class MyStack<T> { private List<T> items; public MyStack() { items = new List<T>(); } public void Push(T item) { items.Add(item); } } ``` 此段代码展示了如何声明一个带有单个类参数`<T>`的类,并在其内部操作该类的实例。这里选择了更灵活的`List<T>`作为存储容器而不是数组,以便更好地管理动态增长的需求[^4]。 #### 类约束的应用 为了使更加实用,有时需要对允许传入的具体类加以限制。例如,当希望某个函数仅能接收实现了特定接口的对象时,则可以通过添加where子句来进行限定: ```csharp public class ExampleClass<T> where T : IComparable, IDisposable { // Class implementation... } ``` 上述语法表示只有那些既继承了IDisposable又实现了IComparable接口的类才可以被当作`ExampleClass<>`的实际参数传递给定界符内的位置。 #### 委托简介 另外值得一提的是委托——一种结合了特性的委托形式。它们允许我们像对待常规方法那样处理具有不同签名的动作或行为模式。比如定义如下所示的一个简单事件处理器模板: ```csharp public delegate TResult Func<in T, out TResult>(T arg); // 或者用于无返回值的情况 public delegate void Action<in T>(T obj); ``` 这里的关键词`in` 和 `out`分别指定了输入/输出方向上的协变特性支持[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值