C#入门经典-------泛型

概述

        泛型使得程序在设计的时候,不必设计其具体的参数,其具体的参数可以延迟到需要的时候

声明或调用。总体上是一种延迟思想,延迟一切可以推迟的。

定义

         一种自定义的强类型化的集合类技术,这种集合类派生于CollectBase,并且可以拥有自己的

视线方法来增删查集合的每个成员。因此,每次创建需要包含在集合中的新类时,需要执行任务,

创建一个新的集合类,继承于CollectBase,他可包含新类型的项,实现所有需要的方法

旧方法
    CollectionClass items = new CollectionClass;
    items.append(new ItemClass);    
  
新方法
     CollectionClass<ItemClass> items  = new CollectionClass<ItemClass>();
     items.append(new ItemClass());
    



        但是,泛型不仅适用于集合、并且不限于类,还可泛型接口、泛型方法、泛型委托。不但能

提高代码的灵活性,还能显著的缩短代码的开发周期。

注意:

        C#的泛型不同于C++的泛型,C++泛型是编译期间的多态,C#的所有操作都是在运行中进行的。.Net运行库允许在需要时动态的生成泛型类,未使用时就不会有存在泛型类。

用法

        可空类型

            泛型使用System.Nullable<T>类型提供了使值类型为空的一种方式。

System.Nullable<int> nullableint;
nullableint = null;

如果bullableint是int类型这是让编译器诧异的操作!

等价于:
    System.Nullable<int> nullableint ;
    nullableint = new System.Nullable<int>();

为空判断:
    ?(nullableint == null);
    
非空判断     
    ?(nullableint.HasValue) 

可为空类型简写: System.Nullable<int> nullableint = int ? nullableint;



    System.Nullable<int> nullint = new System.Nullable<int>();
        if (nullint.HasValue)
        {
            Console.WriteLine("AAA已经初始化过了");
        }
        if (nullint == null)
        { 
            Console.WriteLine("还没有初始化过");
        }

        nullint = 10;
        if (nullint.HasValue)
        {
            Console.WriteLine("BBB已经初始化过了");
        }

    

       注意:可空类型的转换必须显示转换,举例当op是null,就会捕获System.Invalid-OperationException

                int ? op=5;

                int num = (int) op*2;

                //int num = op.Value *2;

??运算符(空接合运算符)

        类似于三目运算符,更加简化代码。若op1为null返回op1,否则返回op2

        op1         ??         op2

        op1 == null         ?         op2        :        op1

?.运算符(空条件运算符)

避免繁杂的空值检查造成代码歧义

int count = customer.orders.Count();

如果order为空会抛出异常,是否和我一样懒得重复的异常处理,那就

int ? count = customer.orders        ?.C        ount();

甚至可以融汇??运算符

int ?count = customer.orders?.Count()        ??        0;

System.Collections.Generic名称空间

这个集合下面包含用于处理集合的泛型类型,泛型集合类型举例:List<T>;Dictionary<K,V>;

这个namespace下可处理泛型列表的排序搜索

定义泛型类型

class MyGenericClass<T1,T2,T3>{.......}

default关键字

常常因为泛型实例不清楚是值类型还是引用类型,因此产生关键字default;

innerT1Object = default(T1);//这里 innerT1Object是一个泛型成员

约束类型

约束泛型为指定类型;

class MyGenericClass<T> where T:constrant1,constrant2...{...}

class MyGenericClass<T1,T2>where T1 : constrant1 where T2 : constrant2{...}

约束必须出现在继承说明符后面;

base-class约束

        class MyGenericClass<T1,T2> where T2:T1{....}

约束从基类继承

public class Farm<T> : IEnumerable<T> where T : Animal{}

class SuperFarm<T> : Farm<T> where T:SuperCow{}//因为SuperCow是Animal的派生类所以合法;

但是,以下则不合法

class SuperFarm<T> :Farm<T> where T:struct{}

定义泛型接口

interface MyFarmingInterface<T> where T:Animal

{

        bool OneMeathod(T animal1,T animal2);

}

定义泛型方法

public class Defaulter

{

        public T GetDefault<T>() =>default(T);        

}

定义泛型委托

public delegate T1 MyDelegate<T1,T2>(T2 op1,T1 op2) where T1 : T2;

变体

运行时多态

Cow myCow = new Cow("Geronimo");

Animal myAnimal = myCow;

但是下面的泛型接口第二行应用却不合法,

IMethod<Cow> cowMethod = myCow;

IMethod<Animal> animalMethod= cowMethod;

因为泛型的类型参数都是不变的,为了使第二行生效,需要引入协变,可以使得IMethod<Cow>和IMethod<Animal>建立一种联系,这样便可以实现接口的多态性。

协变就是不能用接口实现父类到子类的隐式转换;(记忆:父子关系不和“协”,父亲不接纳儿子)

同理下式第二行引用也不合法:

IMethod<Cow> cowMethod = myCow;

IMethod<SuperCow> superCowMethod = cowMethod;

抗变就是不能用接口实现子类到父类的隐式转换;(记忆:反抗时期的儿子,儿子和父亲对抗)

总结

        下次总结,睡了睡了。

  • 16
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值