2

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

 2 years ago
source link: https://www.cnblogs.com/Olive116/p/12334767.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

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];


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK