c#泛型(Generic)

在C#中,泛型是一种强大的特性,它允许你编写可以适用于多种类型的类、方法和数据结构。通过泛型,你可以编写更加灵活和可重用的代码,而不需要对每种数据类型都编写不同的实现。

下面是一个简单的示例,展示了如何创建一个泛型方法:

using System;

public class GenericClass<T>
{
    public T GenericMethod(T value)
    {
        Console.WriteLine("The value is: " + value);
        return value;
    }
}

class Program
{
    static void Main()
    {
        // 创建一个泛型类实例
        GenericClass<int> genericInt = new GenericClass<int>();
        int resultInt = genericInt.GenericMethod(10);

        GenericClass<string> genericString = new GenericClass<string>();
        string resultString = genericString.GenericMethod("Hello");

        // 输出结果
        Console.WriteLine("Result int: " + resultInt);
        Console.WriteLine("Result string: " + resultString);
    }
}

泛型约束

在C#中,有多种泛型约束可以用于限制泛型类型参数。以下是常用的泛型约束:

  1. where T : class

    • 约束类型参数必须是引用类型(类、接口、委托或数组类型),而不能是值类型。
  2. where T : struct

    • 约束类型参数必须是值类型(如基本数据类型、结构体等),而不能是引用类型。
  3. where T : new()

    • 约束类型参数必须具有无参数构造函数。
  4. where T :

    • 约束类型参数必须是指定的基类或其派生类。
  5. where T :

    • 约束类型参数必须实现指定的接口。
  6. where T : U

    • 约束类型参数必须派生自指定的类型参数 U。
  7. where T : U?

    • 约束类型参数必须是可空类型,并且可空类型的基础类型必须满足所指定的约束 U。

这些泛型约束可以单独使用,也可以组合使用,以满足更复杂的约束条件。例如,你可以同时使用多个接口约束类型参数:where T : IComparable, ICloneable。这样就限制了类型参数必须同时实现IComparableICloneable接口。

泛型协变和逆变

当我们在C#中使用泛型协变和逆变时,通常会在接口或委托中定义泛型类型参数,并使用outin关键字来指示协变和逆变。下面是一个简单的示例来展示泛型协变和逆变的具体代码实现:

// 定义一个简单的动物类
class Animal { }

// 定义一个派生类狗
class Dog : Animal { }

// 定义一个接口,使用泛型协变
interface IAnimal<out T>
{
    T GetAnimal();
}

// 实现泛型协变的接口
class AnimalFactory : IAnimal<Dog>
{
    public Dog GetAnimal()
    {
        return new Dog();
    }
}

// 定义一个接口,使用泛型逆变
interface IAnimalHandler<in T>
{
    void HandleAnimal(T animal);
}

// 实现泛型逆变的接口
class AnimalHandler : IAnimalHandler<Animal>
{
    public void HandleAnimal(Animal animal)
    {
        Console.WriteLine("Handling animal");
    }
}

// 在主程序中使用协变和逆变
class Program
{
    static void Main()
    {
        IAnimal<Animal> animal1 = new AnimalFactory();
        Animal animal2 = animal1.GetAnimal(); // 协变允许将IAnimal赋值给IAnimal

        IAnimalHandler<Dog> handler1 = new AnimalHandler();
        handler1.HandleAnimal(new Dog()); // 逆变允许将IAnimalHandler赋值给IAnimalHandler
    }
}

在上面的示例中,我们定义了一个Animal类和一个Dog类作为派生类。然后,我们定义了两个接口IAnimalIAnimalHandler,分别使用了泛型协变和逆变。接着,我们实现了这两个接口,并在主程序中展示了如何使用协变和逆变。

你可能感兴趣的:(c#基础,c#)