当前位置:首页 >> 信息与通信 >>

c#扩展方法封装 ifelse、swithcase及while

c#扩展方法封装 if/else、swith/case 及 while

文章录入:7747.Net 【字体:小大】

责任编辑:7747.Net 更新时间:2010-7-11 14:24:50 87

本文探讨如何使用扩展方法封装 if/else、swith/case 及 while,通过使用这些扩展,写出的 代码将使用很少的大括号{ }。扩展的效果如何,还请大家来评判! 声明:本文属于(改)变(形)态篇,只是提出一种想法,所提供的代码也只是示例,可以 测试通过,但不完善。 首先我们来对看 if/else 和 swith/case,两者在代码中都用来表达分支结构。这里我们统一封 装成一个 If 扩展: public static T If<T>(this T t, Predicate<T> predicate, Action<T> action) where T: class { if(t == null) throw new ArgumentNullException(); if (predicate(t)) action(t); return t; } 看下面的调用代码,生成一个 People 的实例,让他吃饱喝足休息好再工作: public static void Test1() { //常规代码 People people1 = new People { Name = "ldp615", IsHungry = true, IsThirsty = true, IsTired = true }; if (people1.IsHungry) people1.Eat(); if (people1.IsThirsty) people1.Drink(); if (people1.IsTired) people1.Rest(); people1.Work(); //使用扩展方法 People people2 = new People { Name = "ldp615", IsHungry = true, IsThirsty = true, IsTired = true } .If(p => p.IsHungry, p => p.Eat()) .If(p => p.IsThirsty, p => p.Drink()) .If(p => p.IsTired, p => p.Rest()); people2.Work(); } 扩展方法中的 If 可以使用点 “.” 链起来, “链式编程” 请参见我我随笔 称之 , 《c#链式编程》 。 常规代码和使用扩展方法写的代码都在上面,大家比较一下吧。 使用 If 扩展的代码中用了 lambda 表达式,如果前面的“p=>p.”能去掉的话,看起来就比较 舒服了!编译器通过类型及上下文推演,应该可以做得到吧! 给出 People 类如下:

public class People { public string Name { get; set; } public bool IsHungry { get; set; } public bool IsThirsty { get; set; } public bool IsTired { get; set; } public int WorkCount { get; private set; } public void Eat() { Console.WriteLine("Eat"); IsHungry = false; } public void Drink() { Console.WriteLine("Drink"); IsThirsty = false; } public void Rest() { Console.WriteLine("Rest"); IsTired = false; } public void Work() { Console.WriteLine("Work"); IsHungry = IsThirsty = IsTired = true; WorkCount++; } }

对引用类型我们可以使用 Action<T>,也以使用链式编程的方式将多个 If 串起来。 但对值类型来说,就要用 Func<T, T>了,每次返回一个新的值: public static T If<T>(this T t, Predicate<T> predicate, Func<T, T> func) where T : struct { return predicate(t) ? func(t) : t; } 调用代码也要修改:

public static void Test2() {

//扩展方式 int int0 = -121; int int1 = int0.If(i => i < 0, i => -i) .If(i => i > 100, i => i - 100) .If(i => i % 2 == 1, i => i - 1); //常规方式 int int3 = -121; if (int3 < 0) int3 = -int3; if (int3 > 100) int3 -= 100; if (int3 % 2 == 1) int3--; } 引用类型及值类型的扩展我们已经完成,用 string 来测试一下吧,如下:

public static void Test3() { //从邮箱变换成主页 string email = "ldp615@163.com"; string page = email.If(s => s.Contains("@"), s => s.Substring(0, s.IndexOf("@"))) .If(s =>! s.StartsWith("www."), s => s = "www." + s) .If(s =>! s.EndsWith(".com"), s => s += ".com"); } 但编译不通过,会提示错误: 这个错误比较怪,我们写了两个扩展,一个是给值类型的,一个给引用类型,可 string 类型 在这里都不行。这个原因我说不清楚了,还留给园子里高手们吧。 不过专门为 string 写个扩展,这个问题可以化解,如下:

public static string If(this string s, Predicate<string> predicate, Func<string, string> func) { return predicate(s) ? func(s) : s; } 看来扩展方法也是有优先级的:对同一个类进行多次扩展,扩展方法相名,参数也等效(数 量、顺序相同) ,非泛版扩展要比泛型版扩展优先级高。 下面再来看一段 swith 代码,很啰嗦的!这里是为了引出扩展硬写出来的:

public static void Test4() { string englishName = "apple"; string chineseName = string.Empty;

switch (englishName) { case "apple": chineseName = "苹果"; return; case "orange": chineseName = "桔子"; return; case "banana": chineseName = "香蕉"; return; case "pear": chineseName = "梨"; break; default: chineseName = "未知"; break; } Console.WriteLine(chineseName); } 我们把这种方式用扩展方法来完成:

public static TOutput Switch<TOutput, TInput>(this TInput input, IEnumerable<TInput> inputSource, IEnumerable<TOutput> outputSource, TOutput defaultOutput) { IEnumerator<TInput> inputIterator = inputSource.GetEnumerator(); IEnumerator<TOutput> outputIterator = outputSource.GetEnumerator(); TOutput result = defaultOutput; while (inputIterator.MoveNext()) { if (outputIterator.MoveNext()) { if (input.Equals(inputIterator.Current)) { result = outputIterator.Current; break; } } else break; } return result; }

下面的 Test5 是调用:

public static void Test5() { string englishName = "apple"; string chineseName = englishName.Switch( new string[] { "apple", "orange", "banana", "pear" }, new string[] { "苹果", "桔子", "香蕉", "梨" }, "未知" ); Console.WriteLine(chineseName); } 简单清晰明了! 最后是一个对 while 的扩展封装:

public static void While<T>(this T t, T: class { while (predicate(t)) action(t); } 调用代码:

Predicate<T> predicate, Action<T> action) where

public static void Test6() { People people = new People { Name = "Wretch" }; people.While( p => p.WorkCount < 7, p => p.Work() ); people.Rest(); } 这里又“召唤”了一个人,不让吃喝不让休息,连续工作 7 次... 这 while 扩展中只能执行一个 Action<T>,不太好,我们用 params 改进一下:

public static void While<T>(this T t, Predicate<T> predicate, params Action<T>[] actions) where T : class { while (predicate(t)) {

foreach (var action in actions) action(t); } } 再来调用,可以在循环中执行多个操作了,这次舒服工作完吃饭喝水休息,再来工作...

public static void Test7() { People people = new People { Name = "Wretch" }; people.While( p => p.WorkCount < 7, p => p.Work(), p => p.Eat(), p => p.Drink(), p => p.Rest() ); people.Rest(); } 当然前面的 If 也可以这样的,这里只写出一个:

public static T If<T>(this T t, Predicate<T> predicate, params Action<T>[] actions) where T : class { if (t == null) throw new ArgumentNullException(); if (predicate(t)) { foreach (var action in actions) action(t); } return t; }不使用 params,你就要显示声明一个 Action<T>的集合了!

摘自红色黑客联盟(www.7747.net) 原文:http://www.7747.net/kf/201007/52171.html


相关文章:
c#扩展方法封装 ifelse、swithcase及while.doc
c#扩展方法封装 ifelseswithcase及while - c#扩展方法封装 if/else、swith/case 及 while 文章录入:7747.Net 【字体:小大】 责任编...
使用IconHandler 2.0 获取文件图标.pdf
(149) 阅读排行榜 c#扩展方法奇思妙用(6240) c#扩展方法奇思妙用变态篇二:封装 if/elseswith/case及while(4058) ShellIconHandler.dll 这个 dll 用在 ASP....
【完美版本】C#习题册解析.doc
选择分支结构:if-elseswitch-case 循环结构:while...3) C#对运算符_重载方法_ __进行了扩展,不仅可以...7)面向对象编程的重要特征___封装、继承、多态___...
C#复习重点总结.pdf
(if else;switch case) 选择语句依据一个控制表达式...(do ;while ;for;foreach) (1)while 依据其...6、类的方法c#中,数据和操作均封装在类中,...
C#填空题.doc
} } 10C#将文件视为一个字节序列,以流的方式对文件...{ if(value=="男") SexType="先生"; else if...在 switch 语句中,每个语句标号所含关键字 case ...
C#填空题分析.doc
} } 10C#将文件视为一个字节序列,以流的方式对文件...{ if(value=="男") SexType="先生"; else if...在 switch 语句中,每个语句标号所含关键字 case ...
c#学习提纲.doc
与拆箱 4、运算符和表达式 5、选择结构:if-else,switch-case 6、循环结构:while,do-while,for,for...(方法重载) 、扩展方法、 构造函数、析构函数、...
C#试题库2014.doc
if else 语句;switch 语句 3.循环语句:while 语句...9、在 C#中,进行注释有两种方法:使用//和使用“/...22、 ( 封装 )是用一个框架把数据和代码组合在一...
c#复习重点总结.doc
else;switch case) 选择语句 (if else;switch case...(do ;while ;for;foreach) (1)while 依据其...6、类的方法和重载 在 c#中,数据和操作均封装在...
C#总结.doc
在 C 和 C++中是不能 使用关键字的,C#中可以在...If?else? 2. switch?case? 8.循环结构:重复执行...说明:实现循环的方法有如下四种: 1. do?while? ...
1、NET简介及C#数据类型_图文.ppt
数据封装其中,以提高软件的重用性、 灵活性和扩展性...C#的语句:一、选择语句 (if else;switch case) ...二、循环控制(do ;while ;for;foreach) ? for...
单片机控制语音计算器总结报告_图文.doc
设计的主要任务包括两个部分:基础任务与扩展任务。 ...{ if(shift==0) { switch(num) { case 'c':...case '^':d=a;while(--b) a=a*d; break; ...
第2章 程序设计基础_计算机软件及应用_IT/计算机_专业资料.ppt
匹配的时候,就执行该处的 内容,和if语句的else相似...选择结构(switch语句) 注意事项 case后面只能是常量,...{ 循环体语句; } 扩展格式初始化语句; while(判断...
MATLAB7.0使用详解-第8章 M-文件和MATLAB_图文.ppt
程序的分析、调试改良以及MATLAB函数的 扩展知识。...将对照for语句,讲解while循环语句的结构使用方法。...MATLAB中常见的条件分支控制语句有if和switch 语句,...
C语言文件._图文.ppt
( fp1 ); if( EOF == ch ) break; fputc( ch, fp2 ); } while( 1...=EOF) switch(ch) { case ' ': case '\t': case '\n':white++;...
C语言-基本选择题及答案 (自动保存的).doc
switch ( i ) { case case case 9: 10: 11:...while D. if?else B) a=1,b=1 C) C) a=...简单变量做实参时,它和对应形参之间的数据传递方式为...
第4章 MATLAB语言的程序设计_图文.ppt
switch,case和otherwise组成的开关结 while, for循环结构 try 和catch组成的试探...在线交流,有问必答 4.1.1 if, elseelseif组成的条件转移结构 扩展的...
数学建模培训m文件_图文.ppt
? M 文件以 .m 为扩展名。 ? M 文件根据调用...if rem(n, 2)==0 a='even', else a='odd'...n=input( 'n='), switch mod(n,2), case 1...
MATLAB第四讲M文件_图文.ppt
破坏了函数对变量的封装,降低了程序的可读性和 可靠...elseif 条件m 语句组m else 语句组n end 语句...在switch结构中,如果第一个case条 件满足,那么执行...
matlab课件第四章2011.9.22_图文.ppt
并可以 进行程序设计,编写扩展名为.m的M文件, ...在 MATLAB 中包括 for 循环和 while循环。 (1)...在 MATLAB 中有 if-else-end 和 switch-case-...
更多相关标签: