前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >【c#】泛型

【c#】泛型

作者头像
MaybeHC
发布2024-04-23 19:44:33
670
发布2024-04-23 19:44:33
举报
文章被收录于专栏:技术之路技术之路

泛型

一、泛型的引入

1.泛型:宽泛的——不确定的; 型:类型——不确定的类型 2.调用普通方法的时候,参数类型在声明时就确定了,调用按照类型传递参数即可 3.如果可以通过参数推导出来则可以省略尖括号

为什么不能使用object的替代泛型 a.性能问题——装箱拆箱 b.类型安全问题

二、泛型的声明——设计思想

1.泛型方法:在一个方法名称后面多了一个尖括号,尖括号中有占位符 2.延迟声明:声明的时候,只是给一个占位符T T是什么类型?你调用的时候是什么,你说什么就是什么 3.占位符 T-类型参数——类型变量 4.类型参数当做方法的参数的时候,明确参数类型

三、泛型的特点

泛型不是语法糖泛型是由框架升级支持的,使用时CLR需要支持泛型

四、泛型的应用

1.泛型方法——可以一个方法满足不同的类型需求 2.泛型类——可以一个类满足不同类型的需求 3.泛型接口——可以一个接口满足不同类型的需求 4.泛型委托——可以一个委托满足不同类型的需求

五、泛型约束

object类型安全问题:向接收object类型的方法传递类,接收object类型方法中可能会有对类的转换,但是接口没有约束,会导致隐患。

1.基类约束
代码语言:javascript
复制
/// <summary>
/// 基类约束
/// 类型参数设定为people类型
/// 调用时就可以传递People或者People的子类型
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="tParameter"></param>
public static void Show<T>(T tParameter) where T : People
{
	    Console.WriteLine(tParameter.Id);
 	    Console.WriteLine(tParameter.Name);
}
2.接口约束
代码语言:javascript
复制
/// <summary>
/// 接口约束
/// a.把这个T当作ISports
/// b.就只能传递ISporys 这个接口或者时实现过这个接口的类
/// c.可以获取使用接口的功能
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="tParameter"></param>
public static void Show<T>(T tParameter) where T : ISports
{
 	    tParameter.Pingpang();
}
3.引用类型约束
代码语言:javascript
复制
1 	/// <summary>
2 	/// 引用类型约束
3 	/// a.就只能传递引用类型
4 	/// </summary>
5 	/// <typeparam name="T"></typeparam>
6 	/// <param name="tParameter"></param>
7 	public static void ShowClass<T>(T tParameter) where T : class
8 	{
9 	}
4.值类型约束
代码语言:javascript
复制
/// <summary>
/// 值类型约束
/// a.就只能传递值类型
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="tParameter"></param>
public static void ShowStruct<T>(T tParameter) where T : struct
{
}
5.无参数构造函数约束
代码语言:javascript
复制
/// <summary>
/// 无参数构造函数约束
/// a.只能传输无参数构造类
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="tParameter"></param>
public static void ShowNew<T>(T tParameter) where T : new()
{
    T t = new T();
}
6.枚举约束
代码语言:javascript
复制
/// <summary>
/// 枚举约束
/// a.只能传输无参数构造类
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="tParameter"></param>
public static void ShowEnum<T>(T tParameter) where T : Enum
{
}
7.限定泛型继承关系的约束
代码语言:javascript
复制
/// <summary>
/// 限定泛型的继承关系
/// 要不是同一类型要不是继承关系
/// T继承S
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="tParameter"></param>
public static void ShowParent<T,S>(T tParameter) where T : S
{
}

六、泛型缓存

可以根据不同的类型生成一个新的类的副本;

代码语言:javascript
复制
/// <summary>
///泛型缓存:
/// </summary>
/// <typeparam name="T"></typeparam>
public class GenericCache<T>
{
    static GenericCache()
    {
        Console.WriteLine("This is GenericCache 静态构造函数");
        //_TypeTime = string.Format("{0}_{1}", typeof(T).FullName, DateTime.Now.ToString("yyyyMMddHHmmss.fff")); 
        _TypeTime = $"{typeof(T).FullName}_{DateTime.Now.ToString("yyyyMMddHHmmss.fff")}";
    }
    private static string _TypeTime = "";

    public static string GetCache()
    {
        return _TypeTime;
    }

}

调用

代码语言:javascript
复制
Console.WriteLine(GenericCache<int>.GetCache()); //GenericCacheInt
Console.WriteLine(GenericCache<long>.GetCache());// GenericCachelong
Console.WriteLine(GenericCache<DateTime>.GetCache());
Console.WriteLine(GenericCache<string>.GetCache());
Console.WriteLine(GenericCache<GenericCacheTest>.GetCache());

七、泛型的协变和逆变

协变和逆变只支持泛型接口和泛型委托 协变可以让右边使用子类,左边使用父类。 Out类型参数只能做返回值,不能做参数 逆变可以让右边用父类,左边用子类。in类型参数只能做参数,不能作为返回值 协变逆变的存在就是为了满足常规场景添加一个避开风险的约束

不安全场景事例: 以这样一个接口举例

在这里插入图片描述
在这里插入图片描述
代码语言:javascript
复制
public interface ICustomerListOut<T>
{
    T Get();

    void Show(T t);
}

CustomerListOut实现这个接口

代码语言:javascript
复制
public class CustomerListOut<T> : ICustomerListOut<T>
{
    public T Get()
    {
        return default(T);
    }

    public void Show(T t)  
    {

    }
}

以下面的方式调用会出现安全问题

在这里插入图片描述
在这里插入图片描述

在T为Animal时传入了Cat,就会发生错误。 所以才需要用in out来进行约束,来限定,在此类中限定out后,T就不能作为参数使用,就规避了出现错误的可能性。

代码示例:
代码语言:javascript
复制
/// <summary>
/// T 就只能做参数  不能做返回值
/// </summary>
/// <typeparam name="T"></typeparam>
public interface ICustomerListIn<in T>
{
    //T Get();

    void Show(T t);
}

public class CustomerListIn<T> : ICustomerListIn<T>
{
    //public T Get()
    //{
    //    return default(T);
    //}

    public void Show(T t)
    {

    }
}

/// <summary>
/// out 协变 只能是返回结果 ,还是int 也是一种高级约束,避免出现问题
/// 泛型T 就只能做返回值; 不能做参数; 
/// </summary>
/// <typeparam name="T"></typeparam>
public interface ICustomerListOut<out T>
{
    T Get();

    //void Show(T t);
}

public class CustomerListOut<T> : ICustomerListOut<T>
{
    public T Get()
    {
        return default(T);
    }

    public void Show(T t)  //t 是Cat的时候,这会儿你给我传递了一个Animal进来,子类做参数,但是传递了一个父类简历
    {

    }
}
调用
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2024-04-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 泛型
    • 一、泛型的引入
      • 二、泛型的声明——设计思想
        • 三、泛型的特点
          • 四、泛型的应用
            • 五、泛型约束
              • 1.基类约束
              • 2.接口约束
              • 3.引用类型约束
              • 4.值类型约束
              • 5.无参数构造函数约束
              • 6.枚举约束
              • 7.限定泛型继承关系的约束
            • 六、泛型缓存
              • 七、泛型的协变和逆变
                • 代码示例:
                • 调用
            领券
            问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档