C#编码简单性之泛型篇(如何编写简短的C#代码,随时更新)

简介:

这是编码简单性系列中的其中一篇,之前几篇包括代码篇/函数篇/语义篇。 因为要积累案例,会随时更新。

 

之前提到:编码简单性的“心法”就是:只要屏幕上有任何两部分代码看上去相似,则一定有合并办法。而说起相似,没有比switch - case的各段代码更相似的了。如果细数一下自己产品中最长的函数,里边几乎肯定的有一个switch - case,或者一堆if -else if(两者其实等同)。一般各段代码看似相同,又有点不同,既不能变成函数,也不能变成类,怎么办呢?

解决臭长的switch-case的最好方法,就是泛型(在C++时代叫做模板)。泛型不好学,但是却很重要。02年左右的时候曾经作为过程改进人员进行代码审查,无意中发现一段在pagedown的时候做波浪状起伏的代码,观察发现其中有65个函数其实可以缩减为1个函数(没错,65:1),其内容是在5种int常数下,处理13种不同的变量,而处理方法完全相同。这段代码共有4000行,已经耗时一个月,编程者月薪7000(那是10年前,7000元可以购买5平米小产权房,或2平米大产权房);当天下午它们就变成了1个函数,长度不足55行。据此推断,每年因为不能灵活使用泛型而造成的经济损失,可能达到亿元以上。


案例1 2011-05-27 一个简单泛型类

下面一段代码很简短,显得很不值得改造,但其实除了Display之外还有很多函数,其中一些case体很长,而且各种type日后层出不穷,因此不得不进行改造。

Display的目的,是让各种各样的udc们以自己的方式显示器Value中的数值:

 
  1.  
  2. [csharp] view plaincopy  
  3. 01.            
  4. 02.public static MvcHtmlString Display(this HtmlHelper htmlHelper, UDC udc)    
  5. 03.        {    
  6. 04.            switch (udc.Type)    
  7. 05.            {    
  8. 06.                case "Text100":    
  9. 07.                    return new MvcHtmlString((udc.Value != null) ? udc.Value.ToString() : "NULL");    
  10. 08.                case "Text20":    
  11. 09.                    return new MvcHtmlString((udc.Value != null) ? udc.Value.ToString() : "NULL");    
  12. 10.                case "Date":    
  13. 11.                    return new MvcHtmlString(((DateTime)udc.Value).ToShortDateString());    
  14. 12.                default: return new MvcHtmlString(string.Format("Unknown UDC type: {0}", udc.Type));    
  15. 13.            }    
  16. 14.        }    

为了能够拆开这个函数,需要声明

 
  1.  
  2. [csharp] view plaincopy  
  3. 01.        
  4. 02.public interface IUDC    
  5. 03.    {    
  6. 04.        ……    
  7. 05.    
  8. 06.        MvcHtmlString Display { get; }    
  9. 07.        ……    
  10. 08.    
  11. 09.    }    

然后让一个类(这个类一般都存在了)继承这个接口,并实现其方法:

 
  1.  
  2. [csharp] view plaincopy  
  3. 01.        
  4. 02.public partial class UDCText100 : IUDC     
  5. 03.    {    
  6. 04.        ……    
  7. 05.    
  8. 06.        public MvcHtmlString Display { get { return new MvcHtmlString((Value != null) ? Value.ToString() : "NULL"); } }    
  9. 07.        ……    
  10. 08.    
  11. 09.    }    

而显示方式也从@Html.Display(udc)变成@udc.Display。

这段代码整个修改后,原来的5个switch-case只剩下1个,代码明显更内聚了,也就是每次增加一个类型,基本只需要在一个地方(partial class)内完成修改,就可以了;修改的成果在编译时就能确认是否充分和正确(而在其中switch-case中漏掉一个类型,只有在运行的时候case找不到才知道)。案例2 2011-05-29 泛型函数

 
  1.  
  2. [csharp] view plaincopy  
  3. 01.            
  4. 02.private IUDC GetOrDefaultUDC<T, V>(Table<T> table, ..., V defaultValue) where T : class, IUDC, new()    
  5. 03.        {    
  6. 04.            var t = table.SingleOrDefault(...);    
  7. 05.            if (t == null)    
  8. 06.            {    
  9. 07.                t = new T();    
  10. 08.                ...    
  11. 09.                t.OValue = defaultValue;     
  12. 10.                ...    
  13. 11.    
  14. 12.            }    
  15. 13.            return t;    
  16. 14.        }    

这个泛型函数从一类表中取出一条记录,如果没有,则创建它。由于创建的时候需要new 一个新的纪录,而且新纪录依据table的不同,某些字段的缺省值也不同。用传统的方法需要编写很多函数,而且每当出现一种新的这类表,又需要编写新的函数。本文开头提到的的那个65个函数就是因此而产生的。

处理这类情况的心法是:如果发现由于类型的差异一些看起来很像的代码无法合并为函数,那么就应该用泛型了

这种情况下用泛型需要掌握两种主要技术:new()和Ixxx(某Interface)。new的目的是让T可以创建(如果函数中不创建就不需要了),而Interface的目的是保证编译时刻就能确保未来的新类型依然可以使用这个函数(C++的时代只有用到新的类型的时候才可以确认)。


 

这里只谈泛型的应用思想,关于泛型的应用技术,在MSDN有一篇很好的文章可供参考:http://msdn.microsoft.com/en-us/library/ms379564(v=vs.80).aspx。此文将整个C#泛型的发展历程从头到尾讲了一遍。



本文转自火星人陈勇 51CTO博客,原文链接:http://blog.51cto.com/cheny/1100096

相关文章
|
1月前
|
缓存 C# Windows
C#程序如何编译成Native代码
【10月更文挑战第15天】在C#中,可以通过.NET Native和第三方工具(如Ngen.exe)将程序编译成Native代码,以提升性能和启动速度。.NET Native适用于UWP应用,而Ngen.exe则通过预编译托管程序集为本地机器代码来加速启动。不过,这些方法也可能增加编译时间和部署复杂度。
|
1月前
|
C#
C# 图形验证码实现登录校验代码
C# 图形验证码实现登录校验代码
76 2
|
2月前
|
安全 程序员 编译器
C#一分钟浅谈:泛型编程基础
在现代软件开发中,泛型编程是一项关键技能,它使开发者能够编写类型安全且可重用的代码。C# 自 2.0 版本起支持泛型编程,本文将从基础概念入手,逐步深入探讨 C# 中的泛型,并通过具体实例帮助理解常见问题及其解决方法。泛型通过类型参数替代具体类型,提高了代码复用性和类型安全性,减少了运行时性能开销。文章详细介绍了如何定义泛型类和方法,并讨论了常见的易错点及解决方案,帮助读者更好地掌握这一技术。
76 11
|
1月前
|
中间件 数据库连接 API
C#数据分表核心代码
C#数据分表核心代码
36 0
|
1月前
|
存储 C#
C#使用哈夫曼编码实现压缩与解压
C#使用哈夫曼编码实现压缩与解压
26 0
|
3月前
|
开发者 C# Android开发
Xamarin 与 .NET:解锁现代化移动应用开发的超级武器——深入探讨C#与.NET框架如何赋能跨平台应用,实现高效编码与卓越性能
【8月更文挑战第31天】Xamarin 与 .NET 的结合为开发者提供了强大的平台,用于构建现代化移动应用。通过 C# 和 .NET 框架,Xamarin 可以实现一次编写、多平台运行,覆盖 iOS、Android 和 Windows。这种方式不仅节省了开发时间和成本,还保证了应用的一致性和高质量。Xamarin 是一个开源框架,专为跨平台移动应用开发设计,允许使用 C# 语言和 .NET 核心库构建原生应用,并访问各平台特定功能。微软维护的 Xamarin 是 Visual Studio 生态系统的一部分,极大地提高了开发效率。
84 0
|
3月前
|
数据安全/隐私保护 C# UED
利用 Xamarin 开展企业级移动应用开发:从用户登录到客户管理,全面演示C#与Xamarin.Forms构建跨平台CRM应用的实战技巧与代码示例
【8月更文挑战第31天】利用 Xamarin 进行企业级移动应用开发能显著提升效率并确保高质量和高性能。Xamarin 的跨平台特性使得开发者可以通过单一的 C# 代码库构建 iOS、Android 和 Windows 应用,帮助企业快速推出产品并保持一致的用户体验。本文通过一个简单的 CRM 示例应用演示 Xamarin 的使用方法,并提供了具体的代码示例。该应用包括用户登录、客户列表显示和添加新客户等功能。此外,还介绍了如何增强应用的安全性、数据持久化、性能优化及可扩展性,从而构建出功能全面且体验良好的移动应用。
52 0
|
3月前
|
前端开发 开发者 Apache
揭秘Apache Wicket项目结构:如何打造Web应用的钢铁长城,告别混乱代码!
【8月更文挑战第31天】Apache Wicket凭借其组件化设计深受Java Web开发者青睐。本文详细解析了Wicket项目结构,帮助你构建可维护的大型Web应用。通过示例展示了如何使用Maven管理依赖,并组织页面、组件及业务逻辑,确保代码清晰易懂。Wicket提供的页面继承、组件重用等功能进一步增强了项目的可维护性和扩展性。掌握这些技巧,能够显著提升开发效率,构建更稳定的Web应用。
104 0
|
6月前
|
开发框架 前端开发 .NET
C#编程与Web开发
【4月更文挑战第21天】本文探讨了C#在Web开发中的应用,包括使用ASP.NET框架、MVC模式、Web API和Entity Framework。C#作为.NET框架的主要语言,结合这些工具,能创建动态、高效的Web应用。实际案例涉及企业级应用、电子商务和社交媒体平台。尽管面临竞争和挑战,但C#在Web开发领域的前景将持续拓展。
198 3
|
17天前
|
C# 开发者
C# 一分钟浅谈:Code Contracts 与契约编程
【10月更文挑战第26天】本文介绍了 C# 中的 Code Contracts,这是一个强大的工具,用于通过契约编程增强代码的健壮性和可维护性。文章从基本概念入手,详细讲解了前置条件、后置条件和对象不变量的使用方法,并通过具体代码示例进行了说明。同时,文章还探讨了常见的问题和易错点,如忘记启用静态检查、过度依赖契约和性能影响,并提供了相应的解决建议。希望读者能通过本文更好地理解和应用 Code Contracts。
30 3