C#学习第15天:泛型

什么是泛型?


  • 定义:泛型允许您在类、接口和方法中定义占位符,这些占位符在使用时可以指定为具体的类型。
  • 作用:通过减少重复代码和提供更强的类型检查,提高了代码的可重用性和性能。

泛型的核心概念 


1.泛型类

  • 泛型类能够操作特定的数据类型,而不需要为每种数据类型写一个类。提高代码复用性。
using System;
using System.Collections.Generic;

public class GenericContainer<T>
{
    private T item;
    
    // 设置泛型项的值
    public void SetItem(T value) 
    {
        item = value;
    }
    
    // 获取泛型项的值
    public T GetItem()
    {
        return item;
    }
}

使用泛型类示例:

    public static void Demo()
    {
        // 使用int类型
        var intContainer = new GenericContainer<int>();
        intContainer.SetItem(10);
        
        // 使用string类型
        var stringContainer = new GenericContainer<string>();
        stringContainer.SetItem("Hello");
    }

2.泛型方法

可以在非泛型类中定义泛型方法,允许该方法独立于其所在类的参数类型。

public class GenericMethods
{
    // ref关键字表示参数按引用传递
    public void Swap<T>(ref T a, ref T b)
    {
        T temp = a;
        a = b;
        b = temp;
    }

    // 演示多个类型参数的泛型方法
    public TResult Convert<TInput, TResult>(TInput input) where TResult : new()
    {
        // 处理类型转换逻辑
        return new TResult();
    }
}

使用泛型方法的示例:

    public static void Demo()
    {
        var methods = new GenericMethods();
        
        // 演示Swap方法
        int x = 10, y = 20;
        Console.WriteLine($"交换前: x = {x}, y = {y}");
        methods.Swap(ref x, ref y);
        Console.WriteLine($"交换后: x = {x}, y = {y}");

        string str1 = "Hello", str2 = "World";
        Console.WriteLine($"交换前: str1 = {str1}, str2 = {str2}");
        methods.Swap(ref str1, ref str2);
        Console.WriteLine($"交换后: str1 = {str1}, str2 = {str2}");

        // 演示Convert方法
        int number = 42;
        string result = methods.Convert<int, string>(number);
        Console.WriteLine($"转换结果: {result}");
    }

 3.泛型接口

允许接口的方法和属性使用泛型类型参数。

public interface IRepository<T>
{
    void Add(T item);
    void Remove(T item);
    T GetById(int id);
    IEnumerable<T> GetAll();
}

使用示例:

public class User
{
    public int Id { get; set; }
    public string Name { get; set; }
}

// 实现用户仓储类
public class UserRepository : IRepository<User>
{
    private List<User> users = new List<User>();

    public void Add(User item)
    {
        users.Add(item);
    }

    public void Remove(User item)
    {
        users.Remove(item);
    }

    public User GetById(int id)
    {
        return users.FirstOrDefault(u => u.Id == id);
    }

    public IEnumerable<User> GetAll()
    {
        return users;
    }
}

    // 演示仓储接口的使用
public static void Demo()
{
    var userRepo = new UserRepository();
        
    // 添加用户
    userRepo.Add(new User { Id = 1, Name = "张三" });
    userRepo.Add(new User { Id = 2, Name = "李四" });
        
    // 获取所有用户
    var allUsers = userRepo.GetAll();
    foreach (var user in allUsers)
    {
       Console.WriteLine($"用户ID: {user.Id}, 名称: {user.Name}");
    }
        
    // 根据ID获取用户
    var user1 = userRepo.GetById(1);
    Console.WriteLine($"查找到用户: {user1?.Name}");
        
     // 删除用户
    userRepo.Remove(user1);
}

高级主题


约束

限制泛型参数的类型以增加灵活性和安全性。

  • where T : struct:T必须是值类型。
  • where T : class:T必须是引用类型。
  • where T : new():T必须有一个无参构造函数。
  • where T : BaseClass:T必须继承自BaseClass。
  • where T : InterfaceName:T必须实现某接口。
public class Example<T> where T : new()
{
    public T CreateInstance()
    {
        return new T();
    }
}

public class GenericConstraints
{
    public T Sum<T>(T a, T b) where T : struct 
}

 泛型委托

泛型不仅适用于类和方法,还可以用于委托。

public delegate T Transformer<T>(T arg);

class Program
{
    static int Square(int x) => x * x;

    static void Main()
    {
        Transformer<int> transformer = Square;
        Console.WriteLine(transformer(3)); // 输出:9
    }
}

使用场景


1.集合类

  • List<T>, Dictionary<TKey,TValue>, Queue<T>等都是泛型类的例子,可存储任何类型数据。

2.算法实现

  • 可以创建通用的排序、搜索或其他算法,适用于任何类型。

3.类型安全事件处理

  • 泛型委托用于事件系统中,确保类型匹配并提高安全性。

实践习题 


1.创建一个泛型栈类GenericStack<T>,实现基本的栈操作:Push、Pop和Peek。

using System;
using System.Collections.Generic;

public class GenericStack<T>
{
    private List<T> elements = new List<T>();
    // 将元素添加到栈顶的Push操作
    public void Push(T item)
    {
        elements.Add(item);
    }
    // 移除并返回栈顶元素的Pop操作
    public T Pop()
    {
        if (elements.Count == 0)
        {
            throw new InvalidOperationException("The stack is empty.");
        }
        T item = elements[^1]; // ^1 是C# 8.0语法,用于访问最后一个元素
        elements.RemoveAt(elements.Count - 1);
        return item;
    }
    // 返回栈顶元素但不移除的Peek操作
    public T Peek()
    {
        if (elements.Count == 0)
        {
            throw new InvalidOperationException("The stack is empty.");
        }
        return elements[^1];
    }
}

public class Program
{
    public static void Main()
    {
        GenericStack<int> stack = new GenericStack<int>();
        stack.Push(10);
        stack.Push(20);
        stack.Push(30);

        Console.WriteLine(stack.Peek()); // 输出:30
        Console.WriteLine(stack.Pop());  // 输出:30
        Console.WriteLine(stack.Pop());  // 输出:20
    }
}

2.编写一个泛型类LimitedType<T>,仅允许实现了IDisposable接口的类型作为参数,并包含一个释放资源的方法。

using System;

public class LimitedType<T> where T : IDisposable, new()
{
    private T resource;

    public LimitedType()
    {
        resource = new T();
    }

    public void UseResource()
    {
        Console.WriteLine($"Using resource of type {typeof(T).Name}");
        // 假装使用资源
    }

    public void ReleaseResource()
    {
        Console.WriteLine($"Releasing resource of type {typeof(T).Name}");
        resource.Dispose();
    }
}

public class MyResource : IDisposable
{
    public void Dispose()
    {
        Console.WriteLine("MyResource disposed");
    }
}

public class Program
{
    public static void Main()
    {
        LimitedType<MyResource> limitedResource = new LimitedType<MyResource>();
        limitedResource.UseResource();
        limitedResource.ReleaseResource();
    }
}

说明:

  • LimitedType类使用where T : IDisposable, new()约束,这意味着T必须实现IDisposable接口,并且具有无参构造函数。
  • UseResource模拟使用资源,而ReleaseResource负责正确地释放资源。
  • MyResource类实现了IDisposable接口,用于演示如何正确地处置资源。

通过这些例子,我们展示了如何利用泛型提高代码的通用性和灵活性。如果有任何问题或需要进一步讲解,请随时告诉我!
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

ghost143

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值