C#泛型的理解

1 篇文章 0 订阅

一.为什么要使用泛型

1.比如我们又如下三个方法:

        /// <summary>
        /// 打印个int值 
        /// </summary>
        /// <param name="parameter"></param>
        public static void ShowInt(int parameter)
        {
            Console.WriteLine("This is {0},parameter={1},type={2}",
                typeof(CommonMethod).Name, parameter.GetType().Name, parameter);
        }

        /// <summary>
        /// 打印个string值
        /// </summary>
        /// <param name="parameter"></param>
        public static void ShowString(string parameter)
        {
            Console.WriteLine("This is {0},parameter={1},type={2}",
                typeof(CommonMethod).Name, parameter.GetType().Name, parameter);
        }
        /// <summary>
        /// 打印个DateTime值
        /// </summary>
        /// <param name="parameter"></param> 
        public static void ShowDateTime(DateTime parameter)
        {
            Console.WriteLine("This is {0},parameter={1},type={2}",
                typeof(CommonMethod).Name, parameter.GetType().Name, parameter);
        }

调用:

                int iValue = 123;
                string sValue = "456";
                DateTime dtValue = DateTime.Now;
                CommonMethod.ShowInt(iValue);
                CommonMethod.ShowString(sValue);
                CommonMethod.ShowDateTime(dtValue);

        思考:我们可以看到这三个方法基本相同只是参数类型不同,那么我们怎么同一个方法来写呢?

        可能大家首先考虑的是object。

        那么我们先用object实现

        /// <summary>
        /// 打印个object值   
        /// </summary>
        /// <param name="oParameter"></param>
        public static void ShowObject(object oParameter)
        {
            Console.WriteLine("This is {0},parameter={1},type={2}",
                typeof(CommonMethod), oParameter.GetType().Name, oParameter);
        }




        //调用
                object oValue = "678";
                CommonMethod.ShowObject(iValue);
                CommonMethod.ShowObject(sValue);
                CommonMethod.ShowObject(dtValue);
                CommonMethod.ShowObject(oValue);

1.但是我们都知道object是引用类型,存在堆内存中。值类型存在栈内存中。所以上面存在装箱和拆箱。首先值类型先要变成引用类型装箱过程,后面方法执行又要变成值类型拆箱过程。还是一个很消耗资源的过程。这就是性能消耗问题

2.同时存在类型安全问题。比如我再showObject写int a= Convert.ToInt32(oParameter);他在编译的时候不会报错,但是在执行的时候传入不能转成int类型的就会出错。这就是类型安全问题

        /// <summary>
        /// 打印个object值   
        /// </summary>
        /// <param name="oParameter"></param>
        public static void ShowObject(object oParameter)
        {
            Console.WriteLine("This is {0},parameter={1},type={2}",
                typeof(CommonMethod), oParameter.GetType().Name, oParameter);
            int a= Convert.ToInt32(oParameter);//添加
        }

为了解决这两个问题同时又支持一个方法可以传不同的参数类型,所以就出现了泛型.

泛型的优势:比object的性能又快,同时不会出现类型安全问题。(因为在编译时有类型问题就会直接报错)

一、泛型原理:泛型在经过编译以后没有确定类型,它是在运行时CLR 中的及时编译器(jit),确定是某一个具体的类型; 

二、泛型的设计
                1.声明的时候有一个占位符----不确定他的类型
                2.运行的时候确定类型---延迟声明; 

泛型有:泛型方法,泛型类(比如List类),泛型委托,泛型接口等。

        /// <summary>
        /// 泛型方法:不同类型
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="tPrarameter"></param>
        public static void ShowGeneric<T>(T tPrarameter)
        {
            Console.WriteLine("This is {0},parameter={1},type={2}",
               typeof(CommonMethod), tPrarameter.GetType().Name, tPrarameter);
        }


        //调用
                int iValue = 123;
                string sValue = "456";
                DateTime dtValue = DateTime.Now;
                CommonMethod.ShowGeneric<int>(iValue); //
                CommonMethod.ShowGeneric<string>(sValue);
                CommonMethod.ShowGeneric<DateTime>(dtValue);
                CommonMethod.ShowGeneric(oValue);

泛型方法的特点:

                1.调用的时候---指定类型
                2.指定的类型必须和参数类型一致
                3.在调用的时候,如果可以根据参数推导出类型,尖括号中的类型声明可以省略不写;

泛型是如何解决类型安全问题的呢?答案是通过泛型约束

比如我用这些基础类.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace AspNetCore.Generic
{
    public interface ISports
    {
        void Pingpang();
    }

    public interface IWork
    {
        void Work();
    }


    public class People
    {
        public People()
        {

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

        public void Hi()
        { }

    }

    public class Chinese : People, ISports, IWork
    {
         
        public void Tradition()
        {
            Console.WriteLine("仁义礼智信,温良恭俭让");
        }
        public void SayHi()
        {
            Console.WriteLine("吃了么?");
        }

        public void Pingpang()
        {
            Console.WriteLine("打乒乓球...");
        }

        public void Work()
        {
            throw new NotImplementedException();
        }
    }

    public class Hubei : Chinese
    { 
        public string Changjiang { get; set; }
        public void Majiang()
        {
            Console.WriteLine("打麻将啦。。");
        }
    }


    public class Japanese : ISports
    {
        public int Id { get; set; }
        public string Name { get; set; }


        public void Pingpang()
        {
            Console.WriteLine("打乒乓球...");
        }
    }
}

类型约束:

        /// <summary>  
        /// 基类约束,限定必须是People类
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="oParameter"></param>
        public static void Show<T>(T tParameter)   where T:People
        {
            Console.WriteLine("This is {0},parameter={1},type={2}",
                typeof(CommonMethod), tParameter.GetType().Name, tParameter); 
            Console.WriteLine($"People.Id={tParameter.Id}");
            Console.WriteLine($"People.Id={tParameter.Name}");
        }


        /// <summary>
        /// 接口约束:限定T 是ISports接口或者是ISports实现类;
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="tParameter"></param>
        public static void ShowInterface<T>(T tParameter) where T : ISports
        {
            Console.WriteLine("This is {0},parameter={1},type={2}",
                typeof(CommonMethod), tParameter.GetType().Name, tParameter);
            //Console.WriteLine($"People.Id={tParameter.Id}");
            //Console.WriteLine($"People.Id={tParameter.Name}");
            tParameter.Pingpang();
        }

        /// <summary>
        /// 引用类型约束 约束T 必须是引用类型
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="tParameter"></param>
        public static void ShowClass<T>(T tParameter) where T : class
        {
            Console.WriteLine("This is {0},parameter={1},type={2}",
                typeof(CommonMethod), tParameter.GetType().Name, tParameter); 
        }

        /// <summary>
        ///值类型约束: 约束T 必须是值类型
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="tParameter"></param>
        public static void ShowStruct<T>(T tParameter) where T : struct
        {
            Console.WriteLine("This is {0},parameter={1},type={2}",
                typeof(CommonMethod), tParameter.GetType().Name, tParameter);
        }


        /// <summary>
        ///无参数构造函数约束: 约束T 必须有一个无参数构造函数  也就是可以直接New
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="tParameter"></param>
        public static void ShowNew<T>(T tParameter) where T : new()
        {
            Console.WriteLine("This is {0},parameter={1},type={2}",
                typeof(CommonMethod), tParameter.GetType().Name, tParameter);
        }

 调用:

                    {
                        Console.WriteLine("***********************基类约束**************************");
                        GenericConstraint.Show(people);
                        GenericConstraint.Show(chinese);
                        GenericConstraint.Show(hubei);
                        //GenericConstraint.Show(japanese); //不是这个类型 编译器就直接报错;开发者就明确了错误;
                    }

                    {
                        //Console.WriteLine("***********************接口约束**************************");
                        GenericConstraint.ShowInterface(people);
                        //GenericConstraint.ShowInterface(chinese);
                        //GenericConstraint.ShowInterface(hubei);
                        //GenericConstraint.ShowInterface(japanese); //不是这个类型 编译器就直接报错;开发者就明确了错误;
                    }


                    {
                        Console.WriteLine("***********************引用类型约束**************************");
                        GenericConstraint.ShowClass(people);
                        GenericConstraint.ShowClass(chinese);
                        GenericConstraint.ShowClass(hubei);
                        GenericConstraint.ShowClass(japanese); 
                        //GenericConstraint.ShowClass(iValue);
                        //GenericConstraint.ShowClass(sValue);
                        //GenericConstraint.ShowClass(dtValue);


                    }

                    {
                        //Console.WriteLine("***********************值类型约束**************************");
                        //GenericConstraint.ShowStruct(people);
                        //GenericConstraint.ShowStruct(chinese);
                        //GenericConstraint.ShowStruct(hubei);
                        //GenericConstraint.ShowStruct(japanese); //不是这个类型 编译器就直接报错;开发者就明确了错误; 
                        //GenericConstraint.ShowStruct(iValue);
                        //GenericConstraint.ShowStruct(sValue);
                        //GenericConstraint.ShowStruct(dtValue);
                    }
                    {
                        Console.WriteLine("***********************无参数构造函数约束**************************");
                        //People people1 = new People(); 
                        //GenericConstraint.ShowNew(people);
                        GenericConstraint.ShowNew(chinese);
                        GenericConstraint.ShowNew(hubei);
                        GenericConstraint.ShowNew(japanese); //不是这个类型 编译器就直接报错;开发者就明确了错误; 
                        GenericConstraint.ShowNew(iValue);
                        //GenericConstraint.ShowNew(sValue);
                        GenericConstraint.ShowNew(dtValue);
                    }

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

@榴莲酥

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

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

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

打赏作者

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

抵扣说明:

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

余额充值