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>() { , ,  };
var funcs = new List<Func<int>>();
for (int i = ; i < ;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?

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

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

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

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

C# 《编写高质量代码改善建议》整理&笔记 --(三)泛型&委托&事件的更多相关文章

  1. C# 《编写高质量代码改善建议》整理&笔记 --(一)基本语言篇

     题记:这是自己的观后感,工作两年了,本来打算好好学习设计模式,或者作为客户端深入了解GPU编程的,但是突然发现还有这么一本书. <编写高质量代码改善建议>,感觉这正是自己需要的. 我是做 ...

  2. C# 《编写高质量代码改善建议》整理&笔记 --(六)编码规范及习惯

    一.命名规范 1.考虑在命名空间中使用复数 System.AllCollections System.TheCollection 2.用名词和名词组给类型命名 ScoreManager UserCon ...

  3. C# 《编写高质量代码改善建议》整理&笔记 --(五)成员设计

    1.可以字段应该重构为属性 2.谨慎将数组或集合作为属性 数组和集合作为属性存在会引起这样的一个分歧:如果属性是只读的,我们通常会认为他是不可改变的.但是如果将只读属性应用于数组和集合,而元素的内容和 ...

  4. C# 《编写高质量代码改善建议》整理&笔记 --(五)类型设计

    1.区分接口和抽象类的应用场合 区别: ①接口支持多继承,抽象类则不能. ②接口可以包含方法,属性,索引器,事件的签名,但不能有实现,抽象类则可以. ③接口在增加新方法后,所有的继承者都必须重构,否则 ...

  5. C# 《编写高质量代码改善建议》整理&笔记 --(四)资源管理&序列化

    1.显示释放资源需继承接口IDisposable 什么是资源:C#中每一个类型都代表一种资源,而资源又分为以下两类. 托管资源:由CLR管理分配和释放的资源,即从CLR里new出来的对象. 非托管资源 ...

  6. 编写高质量代码改善C#程序的157个建议——建议149:使用表驱动法避免过长的if和switch分支

    建议149:使用表驱动法避免过长的if和switch分支 随着代码变得复杂,我们很容易被过长的if和switch分支困扰. 一个类枚举类型Week如下: enum Week { Monday, Tue ...

  7. 编写高质量代码改善C#程序的157个建议——建议1:正确操作字符串

    最近拜读了陆敏技老师的<编写高质量代码改善C#程序的157个建议>,感觉不错,决定把笔记整理一遍. 建议1: 正确操作字符串 字符串应该是所有编程语言中使用最频繁的一种基础数据类型.如果使 ...

  8. 博友的 编写高质量代码 改善java程序的151个建议

    编写高质量代码 改善java程序的151个建议 http://www.cnblogs.com/selene/category/876189.html

  9. 编写高质量代码--改善python程序的建议(六)

    原文发表在我的博客主页,转载请注明出处! 建议二十八:区别对待可变对象和不可变对象 python中一切皆对象,每一个对象都有一个唯一的标识符(id()).类型(type())以及值,对象根据其值能否修 ...

随机推荐

  1. go语言 nsq源码解读四 nsqlookupd源码options.go、context.go和wait_group_wrapper.go

    本节会解读nsqlookupd.go文件中涉及到的其中三个文件:options.go.context.go和wait_group_wrapper.go. options.go 123456789101 ...

  2. 排序1,2......n的无序数组,时间复杂度为o(n),空间复杂度为o(1)

    #include "stdafx.h" #include <iostream> using namespace std; int _tmain(int argc, _T ...

  3. bzoj3812&uoj37 主旋律

    正着做不好做,于是我们考虑反着来,如何计算一个点集s的答案呢,一定是所有的方案减去不合法的方案,不合法的方案一定是缩完点后是一个DAG,那么就一定有度数为0的scc,于是我们枚举s的子集,就是说这些点 ...

  4. BZOJ_3573_[Hnoi2014]米特运输_树形DP+hash

    BZOJ_3573_[Hnoi2014]米特运输_树形DP+hash 题意: 给你一棵树每个点有一个权值,要求修改最少的权值,使得每个节点的权值等于其儿子的权值和且儿子的权值都相等. 分析: 首先我们 ...

  5. laravel 中的rbac自己简单的实现

    用户表 CREATE TABLE `sys_user` ( `id` varchar(64) COLLATE utf8_bin NOT NULL COMMENT '用户编号', `ids` int(1 ...

  6. angular开发环境配置全套教程

    第一步.安装node.js 1.需要下载的文件路径:https://nodejs.org/en/download/ 2.安装nodejs: 3.验证node.js 4.npm安装以及验证: npm的安 ...

  7. Django之META与前后端交互

    Django之META与前后端交互 1 提交表单之GET 前端提交数据与发送 1)提交表单数据 2)提交JSON数据 后端的数据接收与响应 1)接收GET请求数据 2)接收POST请求数据 3)响应请 ...

  8. Uiautomator分类

    分类中主要使用的类介绍!

  9. ASP.NET Core在Azure Kubernetes Service中的部署和管理

    目录 ASP.NET Core在Azure Kubernetes Service中的部署和管理 目标 准备工作 注册 Azure 账户 AKS文档 进入Azure门户(控制台) 安装 Azure Cl ...

  10. SpringCloud学习系列之四-----配置中心(Config)使用详解

    前言 本篇主要介绍的是SpringCloud中的分布式配置中心(SpringCloud Config)的相关使用教程. SpringCloud Config Config 介绍 Spring Clou ...