C#规范整理·泛型委托事件

本文详细介绍了C#编程中关于泛型、委托和事件的规范,强调了泛型的优先使用,避免泛型类型中声明静态成员,以及正确设置泛型参数约束的重要性。此外,探讨了委托的本质,使用FCL中的委托声明,如Action、Func,以及Lambda表达式的应用。还特别提到了事件的使用,包括event关键字的保护作用和标准事件模型的实现。文章最后讨论了协变和逆变在泛型接口和委托中的应用,为提高代码的复用性和安全性提供指导。
摘要由CSDN通过智能技术生成

基于泛型,我们得以将类型参数化,以便更大范围地进行代码复用。同时,它减少了泛型类及泛型方法中的转型,确保了类型安全。委托本身是一种引用类型,它保存的也是托管堆中对象的引用,只不过这个引用比较特殊,它是对方法的引用。事件本身也是委托,它是委托组,C#中提供了关键字event来对事件进行特别区分。 一旦我们开始编写稍微复杂的C#代码,就肯定离不开泛型、委托和事件。

1.总是优先考虑泛型

泛型的优点是多方面的,无论是泛型类还是泛型方法都同时具备可重用性、类型安全和高效率等特性,这都是非泛型类和非泛型方法无法具备的

2.避免在泛型类型中声明静态成员

  1. 实际上,随着你为T指定不同的数据类型,MyList<T>相应地也变成了不同的数据类型,在它们之间是不共享静态成员的。
  2. 但是若T所指定的数据类型是一致的,那么两个泛型对象间还是可以共享静态成员的,如上文的list1和list2。但是,为了规避因此而引起的混淆,仍旧建议在实际的编码工作中,尽量避免声明泛型类型的静态成员。 
    非泛型类型中的泛型方法并不会在运行时的本地代码中生成不同的类型。 
    例如:
static void Main(string[]args)
{    
    Console.WriteLine(MyList.Func<int>());    
    Console.WriteLine(MyList.Func<int>());    
    Console.WriteLine(MyList.Func<string>());
}

class MyList
{    
    static int count;   
   public static int Func<T>()   
   {       
       return count++;  
  }}
 输出 0 ;1;2

3.为泛型参数设定约束

在编码过程中,应该始终考虑为泛型参数设定约束。约束使泛型参数成为一个实实在在的“对象”,让它具有了我们想要的行为和属性,而不仅仅是一个ob-ject。

指定约束示例:

  • 指定参数是值类型。(除Nullable外) where T:struct
  • 指定参数是引用类型 。 where T:class
  • 指定参数具有无参数的公共构造方法。 where T:new()

    注意,CLR目前只支持无参构造方法约束。

  • 指定参数必须是指定的基类,或者派生自指定的基类。
  • 指定参数必须是指定的接口,或者实现指定的接口。
  • 指定T提供的类型参数必须是为U提供的参数,或者派生自为U提供的参数。 where T:U
  • 可以对同一类型的参数应用多个约束,并且约束自身可以是泛型类型。

4.使用default为泛型类型变量指定初始值

有些算法,比如泛型集合List<T>的Find算法,所查找的对象有可能会是值类型,也有可能是引用类型。在这种算法内部,我们常常会为这些值类型变量或引用类型变量指定默认值。于是,问题来了:值类型变量的默认初始值是0值,而引用类型变量的默认初始值是null值,显然,这会导致下面的代码编译出错:

public T Func<T>()
{    
    T t=null;    
    T t=0;    
    return t;
}

代码"T t=null;"在Visual Studio编译器中会警示:

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值