zoukankan      html  css  js  c++  java
  • C# 《编写高质量代码改善建议》整理&笔记 --(三)泛型&委托&事件

    1.泛型 

      基于泛型,我们可以将类型参数化,以便更大范围地进行代码复用。同时,它减少了泛型类及泛型方法中的转型,

    确保类型安全。

      1)总是优先考虑泛型

        优点:可重用性,类型安全,高效率。

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

        T指定不同的数据类型,MyList<T> 相应的也变成了不同的数据类型,在他们之间不共享静态成员。但是,若T

    所指的数据类型一致,那么两个泛型对象间还是可以共享静态成员的。

      3) 为泛型设定约束

        “约束” 这个词可能会引起歧义,有些人可能认为对泛型参数设定约束是限制参数的使用,实际情况正好相反。

    没有约束的泛型参数作用很有限,只有object的属性和行为,几乎不能在方法中对他们做任何操作。

        倒是“约束” 让泛型参数具有了更多的行为和属性。

        ①指定参数是值类型,可以如下

        

        ②指定参数是引用类型(注意object不能约束,默认约束)

        ③指定参数具有无参数的公共构造方法

        ④可以对同一类型的参数应用多个约束,并且约束本身可以是泛型类型

         编码过程中,应该始终考虑为泛型参数设定约束。约束使泛型参数成为一个实实在在的对象,让它具有了

    我们想要的行为和属性。而不是一个object

      

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

        值类型的默认初始值为0,而引用类型默认初始为null。这样 T t = 0;//会造成编译错误。(参考下列代码)

        

     class Salary
        {
            public void Compute<T> (T t1,T t2) where T : TestItem
            {
                Console.WriteLine(t1.name);
                Console.WriteLine(t1.GetHashCode());
            }
    
            public void Compute<T>(T t)
            {
                Console.WriteLine(t.GetHashCode());
            }
    
            public T FuncTest<T> ()
            {
                T t = default(T);//设置默认值。
                return t;
            }
        }
    
        class TestItem
        {
            public int num;
            public string name;
        }

    2.委托

      1)本质

        ①委托是方法指针,当对其进行实例化的时候,要将引用方法作为它的构造方法的参数 

      2)注意闭包

          闭包理解,本质上说,闭包是一段可以在晚些时候执行的代码块,但是这段代码块依然维护着它

    第一个被创建时环境-即它仍可以使用创建它的方法中的局部变量,即使那个方法已经执行完了。

          换而言之:就是函数引用变量,这个变量跟函数一起存在,即使超出作用域,依然有效。

          闭包的优点,我们可以轻松的访问外层函数定义的变量。比如有如下场景,在winform应用程序中,

    我们希望做这么一个效果,当用户关闭窗体时,给用户一个提示框。

    private void Form1_Load(object sender, EventArgs e)
    {
           string tipWords = "您将关闭当前对话框";
           this.FormClosing += delegate
           {
                MessageBox.Show(tipWords);
           };
    }

    若不使用匿名函数,我们就需要使用其他方式将tipwords变量的值传递给FormClosing注册的处理函数,这样就

    增加了不必要的工作量。

              

          闭包“变量”,而不是闭包“值”。所以在for循环中的添加的匿名函数,只是返回了变量i而不是变量i

    的值。注意,foreach在C#5中做了调整,foreach的每次循环都会是循环变量的一个拷贝,

    这样闭包就看起来关闭了(没有)。但是对for 没有做改动。

          解决闭包的方案

      var values = new List<int>() { 100, 200, 300 };
                var funcs = new List<Func<int>>();
               for (int i = 0; i < 4;i++ )
                {
                    int j = i; //解决方法,或者直接使用foreach,这样本质上都是相同,都是重新拷贝一个新的变量传入。
                    funcs.Add(
                        () => { return j; }
                        );
                }
    
               foreach (var v in funcs)
               {
                   Console.WriteLine(v());
               }

    参考:https://www.cnblogs.com/HQFZ/p/4903400.html 

          https://www.cnblogs.com/jiejie_peng/p/3701070.html

    .  3)事件

      事件本身也是委托,他是委托组,C#提供 event 来对事件进行特别区分。

      他封装了委托类型的变量,使得:在类的内部,不管你声明他是public还是protected,他总是private。在类的外部,

    注册“+=”和“-=”的访问限定符与你在声明事件时使用的访问符相同。

      事件应该由事件发布者触发,而不是由事件的客户端来触发。

     

          4)规范

      ①委托类型的名称都应该以EventHandler结束

      ②事件的命名为委托去掉EventHandler之后剩余的部分。

      5)委托注意

       ①为何委托定义的返回值通常为void?

         委托变量可以供多个订阅者注册,如果定义了返回值,那么多个订阅者的方法都会向发布者返回数值。

    结果就是后面一个返回的的方法值将前面的返回值覆盖掉了,因此,实际上只能获得最后一个方法的返回值。

    除此之外,发布者和订阅者是松耦合的,发布者根本不关心谁订阅了他的事件,为什么要订阅,

    更别说订阅者的返回值了,所以返回订阅者的方法返回值大多数情况没有必要。  

  • 相关阅读:
    分布式计算原理
    消息的有序性
    CAP再解释
    数据建模
    领导层级的跨越
    如何上云|什么是多机房多活架构
    mysql导出导入数据
    Qt 串口 封装好的类 直接使用
    C++ 在类的定义时初始化非静态变量
    Qt error C3646: 未知重写说明符
  • 原文地址:https://www.cnblogs.com/u3ddjw/p/9075354.html
Copyright © 2011-2022 走看看