前言

  泛型并不是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替代方法和匿名方法]的更多相关文章

  1. 编写高质量代码改善C#程序的157个建议[1-3]

    原文:编写高质量代码改善C#程序的157个建议[1-3] 前言 本文主要来学习记录前三个建议. 建议1.正确操作字符串 建议2.使用默认转型方法 建议3.区别对待强制转换与as和is 其中有很多需要理 ...

  2. 读书--编写高质量代码 改善C#程序的157个建议

    最近读了陆敏技写的一本书<<编写高质量代码  改善C#程序的157个建议>>书写的很好.我还看了他的博客http://www.cnblogs.com/luminji . 前面部 ...

  3. 编写高质量代码改善C#程序的157个建议——建议157:从写第一个界面开始,就进行自动化测试

    建议157:从写第一个界面开始,就进行自动化测试 如果说单元测试是白盒测试,那么自动化测试就是黑盒测试.黑盒测试要求捕捉界面上的控件句柄,并对其进行编码,以达到模拟人工操作的目的.具体的自动化测试请学 ...

  4. 编写高质量代码改善C#程序的157个建议——建议156:利用特性为应用程序提供多个版本

    建议156:利用特性为应用程序提供多个版本 基于如下理由,需要为应用程序提供多个版本: 应用程序有体验版和完整功能版. 应用程序在迭代过程中需要屏蔽一些不成熟的功能. 假设我们的应用程序共有两类功能: ...

  5. 编写高质量代码改善C#程序的157个建议——建议155:随生产代码一起提交单元测试代码

    建议155:随生产代码一起提交单元测试代码 首先提出一个问题:我们害怕修改代码吗?是否曾经无数次面对乱糟糟的代码,下决心进行重构,然后在一个月后的某个周一,却收到来自测试版的报告:新的版本,没有之前的 ...

  6. 编写高质量代码改善C#程序的157个建议——建议154:不要过度设计,在敏捷中体会重构的乐趣

    建议154:不要过度设计,在敏捷中体会重构的乐趣 有时候,我们不得不随时更改软件的设计: 如果项目是针对某个大型机构的,不同级别的软件使用者,会提出不同的需求,或者随着关键岗位人员的更替,需求也会随个 ...

  7. 编写高质量代码改善C#程序的157个建议——建议153:若抛出异常,则必须要注释

    建议153:若抛出异常,则必须要注释 有一种必须加注释的场景,即使异常.如果API抛出异常,则必须给出注释.调用者必须通过注释才能知道如何处理那些专有的异常.通常,即便良好的命名也不可能告诉我们方法会 ...

  8. 编写高质量代码改善C#程序的157个建议——建议152:最少,甚至是不要注释

    建议152:最少,甚至是不要注释 以往,我们在代码中不写上几行注释,就会被认为是钟不负责任的态度.现在,这种观点正在改变.试想,如果我们所有的命名全部采用有意义的单词或词组,注释还有多少存在的价值. ...

  9. 编写高质量代码改善C#程序的157个建议——建议151:使用事件访问器替换公开的事件成员变量

    建议151:使用事件访问器替换公开的事件成员变量 事件访问器包含两部分内容:添加访问器和删除访问器.如果涉及公开的事件字段,应该始终使用事件访问器.代码如下所示: class SampleClass ...

随机推荐

  1. Linux系统命令查询软件包

    转载自:http://blog.chinaunix.net/uid-346158-id-2131252.html,http://www.jb51.net/os/RedHat/1102.html, 一. ...

  2. java Timer(定时调用、实现固定时间执行)

    最近需要用到定时调用的功能.可以通过java的Timer类来进行定时调用,下面是有关Timer的一些相关知识. 其实就Timer来讲就是一个调度器,而TimerTask呢只是一个实现了run方法的一个 ...

  3. 如何切入 Linux 内核源代码

    Makefile不是Make Love 从前在学校,混了四年,没有学到任何东西,每天就是逃课,上网,玩游戏,睡觉.毕业的时候,人家跟我说Makefile我完全不知,但是一说Make Love我就来劲了 ...

  4. HFSS学习(一)计划

    2015-11-28 21:05:33 基本概念 边界条件 激励源 建模 网格划分 变量设置与调谐优化 仿真结果 实例 微带线仿真 Ku波段微带线发夹线滤波器仿真 介质滤波器 腔体滤波器 微带一分四功 ...

  5. bzoj-2338 2338: [HNOI2011]数矩形(计算几何)

    题目链接: 2338: [HNOI2011]数矩形 Time Limit: 20 Sec  Memory Limit: 128 MB Description Input   Output 题意: 思路 ...

  6. js立即执行函数: (function ( ){...})( ) 与 (function ( ){...}( )) 有区别?

    没有区别. 你需要明白 IIFE 的原理,我简单说一下: function foo() {...} // 这是定义,Declaration:定义只是让解释器知道其存在,但是不会运行. foo(); / ...

  7. 彻底解决Spring MVC 中文乱码 问题

    1:表单提交controller获得中文参数后乱码解决方案 注意: jsp页面编码设置为UTF-8 form表单提交方式为必须为post,get方式下面spring编码过滤器不起效果 <%@ p ...

  8. eclipse代码自动提示设置、如何配置eclipse的代码自动提示功能(同时解决自动补全变量名的问题)?

    对于编程人员来说,要记住大量的类名或类方法的名字,着实不是一件容易的事情.如果要IDE能够自动补全代码,那将为我们编程人员带来很大帮助. eclipse代码里面的代码提示功能默认是关闭的,只有输入“. ...

  9. win10自动更新彻底关闭

    http://app.techweb.com.cn/wp/2016-10-24/2418646.shtml

  10. 13Spring_AOP编程(AspectJ)_后置通知

    后置通知和前置通知差不多.最大的特点是因为后置通知是运行在目标方法之后的,所以他可以拿到目标方法的运行的结果. 给出案例: 案例结构图: