编写高质量代码改善C#程序的157个建议[为泛型指定初始值、使用委托声明、使用Lambda替代方法和匿名方法]
前言
泛型并不是C#语言一开始就带有的特性,而是在FCL2.0之后实现的新功能。基于泛型,我们得以将类型参数化,以便更大范围地进行代码复用。同时,它减少了泛型类及泛型方法中的转型,确保了类型安全。委托本身是一种引用类型,它保存的也是托管堆中对象的引用,只不过这个引用比较特殊,它是对方法的引用。事件本身也是委托,它是委托组,C#中提供了关键字event来对事件进行特别区分。一旦我们开始编写稍微复杂的C#代码,就肯定离不开泛型、委托和事件。本章将针对这三个方面进行说明。
本文已更新至http://www.cnblogs.com/aehyok/p/3624579.html 。本文主要学习记录以下内容:
建议35、使用default为泛型类型指定初始值
建议36、使用FCL中的委托声明
建议37、使用lambda表达式代替方法和匿名方法
建议35、使用default为泛型类型指定初始值
有些算法,比如泛型集合List<T>的Find算法,所查找的对象有可能会是值类型,也有可能是引用类型。在这种算法内部,我们常常会为这些值类型变量或引用类型变量指定默认值。于是,问题来了:值类型变来那个的默认初始值是0值,而引用类型变量的默认初始值是null值,显然,这会导致下面编译出错:
C#编译器会阻止这样的代码通过编译。要让编译器接收为一个泛型类型参数指定一个初始值,最妥当的办法就是使用default关键字。所以,在上面的代码应该改为:
public T Func<T>()
{
T t = default(T);
return t;
}
这样如果它在运行时碰到的T是一个整型,那么运行时会为其赋值0;如果T在运行时是一个Person这样的引用类型,则会为其赋null值。
建议36、使用FCL中的委托声明
要注意FCL中存在三类这样的委托声明,他们分别是:Action、Func、Predicate。尤其是在他们的泛型版本出来以后,已经能够满足我们在实际编码过程中的大部分需要。
这里是之前一篇关于Action、Func、Predicate的有关介绍http://www.cnblogs.com/aehyok/p/3382291.html
除了Action、Func、Predicate外,FCL中还有用于标识特殊含义的委托声明。如用于表示注册事件方法的委托声明:
public delegate void EventHandler(object sender,EventArgs e); public delegate void EnentHandler<TEventArgs>(object sender,TEventArgs e);
表示线程的委托声明:
public delegate void ThreadStart(); public delegate void ParameterizedThreadStart(object obj);
表示异步回调的委托声明:
public delegate void AsyncCallback(IAsyncResult ar);
在FCL中没一类委托声明都代表一类特殊的用途,虽然可以使用自己的委托声明来代替,但是这样做不仅没有必要,而且会让代码失去简洁性和标准型。在我们实现自己的委托声明前,应该首先查看MSDN,确信有必要之后才这样做。
建议37、使用lambda表达式代替方法和匿名方法
首先我们使用Action和Func来做一个简单的小例子,控制台应用程序代码如下所示:
第一个版本
class Program
{
static int Add(int i, int j)
{
return i + j;
} static void Print(string message)
{
Console.WriteLine(message);
} static void Main(string[] args)
{
Func<int, int, int> add = Add;
Action<string> print = Print;
print(add(, ).ToString());
Console.ReadLine();
}
}
实际上要完成上面的功能,还有多种编码方式,先来看一种最中规中矩的方式,同时也是最繁琐的写法:
第二个版本
class Program
{
static int Add(int i, int j)
{
return i + j;
} static void Print(string message)
{
Console.WriteLine(message);
} static void Main(string[] args)
{
Func<int, int, int> add = new Func<int,int,int>(Add);
Action<string> print =new Action<string>(Print);
print(add(, ).ToString());
Console.ReadLine();
}
}
其实也就是将第一个版本稍作调整。从上面的写法中也可以看出:Add方法和Print方法实际上都只有一条语句,因此,使用匿名方法也许是一种更好的选择:
第三个版本
static void Main(string[] args)
{
Func<int, int, int> add = new Func<int,int,int>(delegate(int i,int j)
{
return i+j;
});
Action<string> print =new Action<string>(delegate(string message)
{
Console.WriteLine(message);
});
print(add(, ).ToString());
Console.ReadLine();
}
使用匿名方法以后,我们不需要在Main方法外部声明两个方法了,可以直接在Main这个工作方法中完成所有的代码编写,而且不会影响代码清晰性。实际上,所有代码行数不超过3行的方法(条件是它不倍重用),我们都建议采用这种方式来编写。上面的版本继续改进:
第四个版本
static void Main(string[] args)
{
Func<int, int, int> add = delegate(int i,int j)
{
return i+j;
};
Action<string> print =delegate(string message)
{
Console.WriteLine(message);
};
print(add(, ).ToString());
Console.ReadLine();
}
以上代码看上去更简化了,不过,最终极的改进是使用lambda表达式:
第五个版本
static void Main(string[] args)
{
Func<int, int, int> add = (x, y) => x + y;
Action<string> print = (message) => Console.WriteLine(message);
print(add(, ).ToString());
Console.ReadLine();
}
Lambda表达式操作符”=>“的左侧是方法的参数,右侧是方法体,其本质是匿名方法。实际上,经过编译后Lambda表达式就是一个匿名方法。我们应该在实际的编码工作中熟练运用它,避免写出繁琐且不美观的代码。
英语小贴士
1、Your passport and declaration card, please.——请出示护照和申报单。
2、This is a souvenir that I'm taking to Taiwan.——这是我要带去台湾的当地纪念品。
3、Do you have anything to declare?——是否有任何东西需要申报?
4、Do you have any liquor or cigarettes?——你有携带任何酒类或香烟吗? No, I don't.——没有。
5、Yes, I have two bottles of whisky.——是的,我带了两瓶酒。
6、Please open this bag.——请打开这个袋子。
7、The camera is for my personal use.——这个相机是我私人使用的。
8、What are these?——这些东西是做何用?
9、You'll have to pay duty on this.——你必须为这项物品缴付税金。
10、These are for my personal use.——这些是我私人使用的东西。
11、Do you have any other baggage?——你还有其它行李吗?
12、These are gifts for my friends.——这些是给朋友的礼物。
13、O.K. Please give this declaration card to that officer at the exit.——好了!请将这张申报卡交给出口处的官员。
作者:aehyok
出处:http://www.cnblogs.com/aehyok/
感谢您的阅读,如果您对我的博客所讲述的内容有兴趣,那不妨点个推荐吧,谢谢支持:-O。
编写高质量代码改善C#程序的157个建议[为泛型指定初始值、使用委托声明、使用Lambda替代方法和匿名方法]的更多相关文章
- 编写高质量代码改善C#程序的157个建议[1-3]
原文:编写高质量代码改善C#程序的157个建议[1-3] 前言 本文主要来学习记录前三个建议. 建议1.正确操作字符串 建议2.使用默认转型方法 建议3.区别对待强制转换与as和is 其中有很多需要理 ...
- 读书--编写高质量代码 改善C#程序的157个建议
最近读了陆敏技写的一本书<<编写高质量代码 改善C#程序的157个建议>>书写的很好.我还看了他的博客http://www.cnblogs.com/luminji . 前面部 ...
- 编写高质量代码改善C#程序的157个建议——建议157:从写第一个界面开始,就进行自动化测试
建议157:从写第一个界面开始,就进行自动化测试 如果说单元测试是白盒测试,那么自动化测试就是黑盒测试.黑盒测试要求捕捉界面上的控件句柄,并对其进行编码,以达到模拟人工操作的目的.具体的自动化测试请学 ...
- 编写高质量代码改善C#程序的157个建议——建议156:利用特性为应用程序提供多个版本
建议156:利用特性为应用程序提供多个版本 基于如下理由,需要为应用程序提供多个版本: 应用程序有体验版和完整功能版. 应用程序在迭代过程中需要屏蔽一些不成熟的功能. 假设我们的应用程序共有两类功能: ...
- 编写高质量代码改善C#程序的157个建议——建议155:随生产代码一起提交单元测试代码
建议155:随生产代码一起提交单元测试代码 首先提出一个问题:我们害怕修改代码吗?是否曾经无数次面对乱糟糟的代码,下决心进行重构,然后在一个月后的某个周一,却收到来自测试版的报告:新的版本,没有之前的 ...
- 编写高质量代码改善C#程序的157个建议——建议154:不要过度设计,在敏捷中体会重构的乐趣
建议154:不要过度设计,在敏捷中体会重构的乐趣 有时候,我们不得不随时更改软件的设计: 如果项目是针对某个大型机构的,不同级别的软件使用者,会提出不同的需求,或者随着关键岗位人员的更替,需求也会随个 ...
- 编写高质量代码改善C#程序的157个建议——建议153:若抛出异常,则必须要注释
建议153:若抛出异常,则必须要注释 有一种必须加注释的场景,即使异常.如果API抛出异常,则必须给出注释.调用者必须通过注释才能知道如何处理那些专有的异常.通常,即便良好的命名也不可能告诉我们方法会 ...
- 编写高质量代码改善C#程序的157个建议——建议152:最少,甚至是不要注释
建议152:最少,甚至是不要注释 以往,我们在代码中不写上几行注释,就会被认为是钟不负责任的态度.现在,这种观点正在改变.试想,如果我们所有的命名全部采用有意义的单词或词组,注释还有多少存在的价值. ...
- 编写高质量代码改善C#程序的157个建议——建议151:使用事件访问器替换公开的事件成员变量
建议151:使用事件访问器替换公开的事件成员变量 事件访问器包含两部分内容:添加访问器和删除访问器.如果涉及公开的事件字段,应该始终使用事件访问器.代码如下所示: class SampleClass ...
随机推荐
- sql date时间加减几天几小时
//时间转成年月日时分秒select date_format(now(),'%Y%m%d%H%i%S')//时间转成年月日select date_format(now(),'%Y%m%d')//去年此 ...
- apache性能测试工具ab使用详解
下面我们对这些参数,进行相关说明.如下:-n在测试会话中所执行的请求个数.默认时,仅执行一个请求.-c一次产生的请求个数.默认是一次一个.-t测试所进行的最大秒数.其内部隐含值是-n 50000,它可 ...
- Design Pattern :Factory and Reflect in java
interface page { void Render(); } class pageA implements page { @Override public void Re ...
- 什么办法可以替代distinct
今天在论坛上看到一个面试题,是说有什么办法可以替代distinct,得到同样的结果.答案都被大家说的差不多了,发现挺有意思的,就记录一下: SQL> select num from t1; ...
- LeetCode题解-----Majority Element II 摩尔投票法
题目描述: Given an integer array of size n, find all elements that appear more than ⌊ n/3 ⌋ times. The a ...
- 边工作边刷题:70天一遍leetcode: day 86-2
Best Meeting Point 要点: 题本身不难理解,manhattan distance.follow up就变成weighted了(因为一个地方可以有多个住户) 注意input是grid的 ...
- 基础KMP两道
1. HDU 1711 Number Sequence 代码: #include <iostream> #include <cstdio> #include <cstri ...
- MATLAB基本命令
eye(n)创建n阶单位矩阵 zeros(n)创建n阶0方阵 rand(m,n)创建m*n阶元素为从0到1的均匀分布的随机数矩阵 round(A)对矩阵A中所有元素进行四舍五入运算 A^-1用幂运算求 ...
- (转)轻量级JS焦点图/轮换图myFocus V2源码下载及安装教程
myFocus是一个专注于焦点图/轮换图制作的JS库,它小巧而且是完全独立的JS库,用它可以轻松的制作出网上绝大部分常见的焦点图(甚至包括flash焦点图),而且制作出的焦点图体积也非常的小(1KB左 ...
- jQuery使用ajax跨域获取数据
var webMethod = "http://localhost:54473/Service1.asmx/HelloWorld"; jQuery.support.cors = ...