.NET知识梳理——1.泛型

Posted 墨遥

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了.NET知识梳理——1.泛型相关的知识,希望对你有一定的参考价值。

1. 泛型Generic

1.1        引入泛型:延迟声明

泛型方法声明时,并未写死类型,在调用的时候再指定类型。

延迟声明:推迟一切可以推迟的。

1.2        如何声明和使用泛型

泛型方法:方法名称后面加上尖括号,里面是类型参数

类型参数实际上就是一个类型T声明,方法就可以用这个类型T了。

如下所示:

public static void Show<T>(T t)

       

            Console.WriteLine($"This is typeof(CustomMethod),paramater=t.GetType().Name,value=t");

       

1.3        泛型的好处和原理

泛型方法性能跟普通方法一致,泛型声明方法时,并未写死类型,T是什么类型,只有在调用的时候才知道,一个方法能满足不同类型。

1.4        泛型类、泛型方法、泛型接口、泛型委托

1.4.1  泛型类型

一个类满足不同类型的需求

具体如下:

public class BaseModel

   

        public int Id get; set;

   

    public class GenericClass<T>

        where T:BaseModel//为泛型基类约束

   

 

   

1.4.2  泛型方法

一个方法满足不同类型的需求

具体如下:

public static void Show<T>(T t)

       

            Console.WriteLine($"This is typeof(CustomMethod),paramater=t.GetType().Name,value=t");

       

1.4.3  泛型接口

一个接口满足不同类型的需求

   //泛型接口

    public interface IGenericInterface<T>

   

        public void  SayHi(T t);

1.4.4  泛型委托

一个委托满足不同类型的需求

public delegate void Do<T>(T t);

1.5        泛型约束

没有约束,泛型会很局限。主要有5中泛型的约束。如下:

1.5.1  基类约束

Where T:BaseModel

可以把BaseModel当作基类

只有该类型的对象或从该类型派生出的对象,可被用作类型参数。(密封类约束的不行,因为没有意义。)

//基类

    public class BaseModel

   

        public int Id get; set;

   

    //泛型类

    public class GenericClass<T>

        where T:BaseModel//为泛型基类约束

   

 

调用:

  GenericConstraint.Show<BeiJing>(new BeiJing());

1.5.2  引用类型约束

 

//引用类型约束

        public static T Get<T>() where T:class

       

            return default(T);//default是关键字,根据类型T返回对应的默认值

       

调用:

GenericConstraint.Get<Person>(new Person());

1.5.3  值类型约束

 

  //值类型约束

        Public static D GetD<D>() where D:struct

       

            return default(D);

       

调用:

GenericConstraint.GetD<int>(116);

1.5.4  无参数构造函数

 

//无参数构造函数约束

        Public static S GetS<S>()

            where S: new()//无餐构造函数约束

             

            return new S();

       

调用:

GenericConstraint.GetS<Chinese>();

1.5.5  接口约束

 

//接口约束

        public static void Show2<T>(T t) where T : ISports

       

            t.Basketball();

       

调用:

GenericConstraint.Show2<USA>(new USA());

1.6        协变、逆变

所谓协变、逆变都是跟泛型有关的(多用在接口)。

1.6.1  协变

修饰返回值

让右边用子类,让泛型用起来更方便(子类转父类)

Out修饰,协变后只能是返回结果,不能做参数

IEnumerable<Bird> birdList=new List<Sparrow>();

  //out 协变,只能是返回结果(子类转父类)

    public interface ICustomerListOut<out T>

   

        T Get();

   

 

    public class CustomerListOut<T>:ICustomerListOut<T>

   

        public T Get()

       

            return default(T);

       

 

ICustomerListOut<Bird> list2 = new CustomerListOut<Sparrow>();

            Func<Bird> func = new Func<Sparrow>(() => null);

            IEnumerable<Bird> list3 = new List<Sparrow>();

1.6.2  逆变

修饰传入参数

让右边可以用父类,让泛型用起来更方便(父类转子类)

In修饰,逆变后只能当作参数

//in 逆变 只能是输入参数(父类转子类)

    public interface ICustomerListIn<in T>

   

        void Show(T t);

   

    public class CustomerListIn<T>:ICustomerListIn<T>

   

        public void Show(T t)

       

            Console.WriteLine(t.GetType().Name);

       

  //逆变

            ICustomerListIn<Sparrow> list1 = new CustomerListIn<Bird>();

            Action<Sparrow> action = new Action<Bird>((i) => );

 

public interface IMyList<in inT,out outT>

   

        void Show(inT t);

        outT Get();

        outT Do(inT t);

   

 

    public class MyList<T, T1> : IMyList<T, T1>

   

        public void Show(T t)

       

            Console.WriteLine(t.GetType().Name);

       

 

        public T1 Get()

       

            Console.WriteLine(typeof(T1).Name);

            return default(T1);

       

 

        public T1 Do(T t)

       

            Console.WriteLine(t.GetType().Name);

            Console.WriteLine(typeof(T1).Name);

            return default(T1);

       

   

   IMyList<Sparrow, Bird> myList1 = new MyList<Sparrow, Bird>();

    IMyList<Sparrow, Bird> myList2 = new MyList<Sparrow, Sparrow>();//协变

    IMyList<Sparrow, Bird> myList3 = new MyList<Bird, Bird>();//逆变

IMyList<Sparrow, Bird> myList4 = new MyList<Bird, Sparrow>();//逆变+协变

1.7        泛型缓存

泛型缓存,每个类型都会生成一个不同的副本(适合不同类型需要缓存一份数据的场景)

  public class GenericCache<T>

   

        private static string _TypeTime = "";

        static GenericCache()

       

            Console.WriteLine("This is GenericCache 静态构造函数");

            _TypeTime = $"typeof(T).FullName_DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss")";

       

 

        public static string GetCache()

       

            return _TypeTime;

       

 

/// <summary>

    /// 字典缓存:静态属性常驻内存

    /// </summary>

    public class DictionaryCache

   

        private static Dictionary<Type, string> _TypeTimeDictionary = null;

        static DictionaryCache()

       

            Console.WriteLine("This is DictionaryCache 静态构造函数");

            _TypeTimeDictionary = new Dictionary<Type, string>();

       

        public static string GetCache<T>()

       

            Type type = typeof(Type);

            if (!_TypeTimeDictionary.ContainsKey(type))

                _TypeTimeDictionary[type] = $"typeof(T).FullName_DateTime.Now.ToString("yyyy-MM-dd HH mm:ss")";

            return _TypeTimeDictionary[type];

       

   

以上是关于.NET知识梳理——1.泛型的主要内容,如果未能解决你的问题,请参考以下文章

HiHoCoder1671 : 反转子串([Offer收割]编程练习赛41)(占位)

.NET知识梳理——5.委托

.NET知识梳理——5.委托

.NET知识梳理——7.Linq

.NET知识梳理——7.Linq

.NET知识梳理——6.lambda