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

简介:

以前写C++的时候曾经在自己网站上发表过一个编码“简单性”之文章,现在编写C#了才发现自己无意之间就会写下一些浪费屏幕的代码。

下面是自己编码中偶然发现的一些案例,欢迎中等水平的编程者参考。因为要积累案例,所以随时更新。


编码简单性的“心法”就是:只要屏幕上有任何两部分代码看上去相似,则一定有合并办法。

无论在微观还是宏观层面上这一点都适合。在02年的时候,我们曾在2小时内把一个程序员的4000多行的65个函数变为一个函数,相当于一个月的工作量被取代;04年则令人发指地发生了1个人用1.5年重新编写了13个人编写了9年的程序的事件。

因此,应随时关注代码中的“不简洁”现象,一旦放任其发生,软件将很难维护。


案例1 合并相似代码

以前遇到过的最极端的例子是:

 

switch (n)

{

case 1: return 1;

case 2: return 2;

case 3: return 3;

case 4: return 4;

case 5: return 5;

case 6: return 6;

default: return n;

}

这段代码其实相当于:return n;

这可不是个笑话,是01年一位还不错的同事编写的,原封未动就是这个样子6个整数。当我们指出来的时候,她忍不住笑了……人就这样,总有走火入魔的时候。

2011-07-31:今天不小心自己写的一段代码:

if (!result.Contains("true"))
{
_repSFC.GrantAuthorityToRole(authority, role, false);
}
if (result.Contains("true"))
{
_repSFC.GrantAuthorityToRole(authority, role, true);
}
其实就是:

_repSFC.GrantAuthorityToRole(authority, role, result.Contains("true"));
 

要发现它们,只需要牢记心法:只要屏幕上有任何两部分代码看上去相似,则一定有合并办法。

 

 


 

 

 

案例1.5 多用?+:语法

另一个小案例:

if (Misc == null)
return SFCCatches.LinkP2Cs.Where(i => i.P == p && i.C == c);
else
return SFCCatches.LinkP2Cs.Where(i => i.P == p && i.C == c && i.Misc == Misc);
改为:

return SFCCatches.LinkP2Cs.Where(i => i.P == p && i.C == c && (Misc == null ? true : i.Misc == Misc));
有时候感觉这种写法有点花哨,但是习惯以后,实际可读性要高得多,尤其如果单行代码挺长的时候。


案例2 推迟分支(请先看案例4)

这个长一些,原来的代码是aspx,在重构成Razor的时候发现可以简化。

<% foreach ( var techDebt in Model.TechDebts) 
{ %>
<% if (techDebt.IsOpen == true) 
{ %>
<div class = "Black">
<a href="/Agile/TechDebts/Edit/<%= techDebt.TechDebtID %>" target = "_blank" ><img title = "编辑" alt = "编辑" class = "icons" src="../../../../Resouces/Images/XXX/TechDebts/TechDebtOpening.png" /></a>
<%= techDebt.Type %>-<%= techDebt.Title %><br />
</div>
<%}
else
{ %>
<div class = "Gray">
<a href="/Agile/TechDebts/Edit/<%= techDebt.TechDebtID %>" target = "_blank" ><img title = "编辑" alt = "编辑" class = "icons" src="../../../../Resouces/Images/XXX/TechDebts/TechDebtsClosed.png" /></a>
<%= techDebt.Type %>-<%= techDebt.Title %><br />
</div>
<%} %>
<%} %>
变成Razor后等同于:

@foreach ( var techDebt in Model.TechDebts) 

string color = techDebt.IsOpen ? "Black" : "Gray"; //也可以放到下面的@color那里,但不太直观。
string img = techDebt.IsOpen ? "TechDebtOpening.png" : "TechDebtsClosed.png"; //同上。
<div class = @color>
<a href="/Agile/TechDebts/Edit/@techDebt.TechDebtID" target = "_blank" ><img title = "编辑" alt = "编辑" class = "icons" src="../../../../Resouces/Images/XXX/TechDebts/@img" /></a>
@techDebt.Type-@techDebt.Title<br />
</div>
}

19行代码变成9行。虽然看起来不起眼,但同比例放大10000倍看:把9万行代码编写成19万行,绝对是一个灾难。

同时注意color/img的处理,因为若把他们嵌入下面的代码中,代码会显得不直观,所以无需处理。毕竟看似多了2行“无用代码”,但他们与别处并无重复,理解起来也更简单。因此简单性是信息的简单性/无重复性,而不是简单地删除分号。


案例3

下面一段代码中,三个TD中的三个函数PrevViews/SameViews/NextViews破坏了简单的合并:

<td>
<ol id = "@Model.DropableID("PREV")" class = "dragable">
@foreach (var view in Model.PrevViews())
{
<li class = "black" id = "@view.DragableID()">
@Html.ImageLink("../../Resouces/Images/" + @view.Area + "/" + @view.Controller + "/" + @view.Action + "16.png",
view.Title, "imagelink", false, view.Action, view.Controller, view.Area, new { }, new { }, new { })
@(view.Title + "(" + view.Area + "/" + view.Controller + "/" + view.Action + ")")<br />
</li>
}
<br />
</ol>
</td>
<td>
<ol id = "@Model.DropableID("SAME")" class = "dragable">
@foreach (var view in SFCView.SameViews())
{
<li class = "black" id = "@view.DragableID()">
@Html.ImageLink("../../Resouces/Images/" + @view.Area + "/" + @view.Controller + "/" + @view.Action + "16.png",
view.Title, "imagelink", false, view.Action, view.Controller, view.Area, new { }, new { }, new { })
@(view.Title + "(" + view.Area + "/" + view.Controller + "/" + view.Action + ")")<br />
</li>
}
<br />
</ol>
</td>
<td>
<ol id = "@Model.DropableID("NEXT")" class = "dragable">
@foreach (var view in SFCView.NextViews())
{
<li class = "black" id = "@view.DragableID()">
@Html.ImageLink("../../Resouces/Images/" + @view.Area + "/" + @view.Controller + "/" + @view.Action + "16.png",
view.Title, "imagelink", false, view.Action, view.Controller, view.Area, new { }, new { }, new { })
@(view.Title + "(" + view.Area + "/" + view.Controller + "/" + view.Action + ")")<br />
</li>
}
<br />
</ol>
</td>
解决方法是使用Model传入三个IEnumerable:

<td>
<ol id = "@Model.DroppableID(SFCView.PREV)" class = "dragable">
@{Html.RenderPartial("_ViewList", Model.RelatedViews(SFCView.PREV));}
<br />
</ol>
</td>
<td>
<ol id = "@Model.DroppableID(SFCView.SAME)" class = "dragable">
@{Html.RenderPartial("_ViewList", Model.RelatedViews(SFCView.SAME));}
<br />
</ol>
</td>
<td>
<ol id = "@Model.DroppableID(SFCView.NEXT)" class = "dragable">
@{Html.RenderPartial("_ViewList", Model.RelatedViews(SFCView.NEXT));}
<br />
</ol>
</td>
这里就固定三种情况,基本上这样可读性和可维护性就可以了。

如果重复的次数更多,就要考虑把td一起搬进一个更大的循环体中。


案例4 2011-05-05:推迟分支

大致意思就是不要写:

if (...)

{

A();

B();

}

else

{

A();

C();

}

而是要写

A();

if (...)

{

B();

}

else

{

C();

}

心法是:任何两个地方看上去相似,就可以简化。技法是:相同部分放在分支前或后,不同部分才是分支。

这个案例看起来是愚蠢的,因为谁能看不出来呢,但实际结果不然,比如下面这段今天刚要写的代码(在一个url后面加上新的参数zoom=1):

url = (uri.Query.Count() == 0) ? uri.PathAndQuery + "?zoom=" + level : uri.PathAndQuery + "&zoom=" + level;

其实应该是:

uri.PathAndQuery + (uri.Query.Count() == 0 ? "?" : "&") + "zoom=" + level;

更隐蔽的是案例2。


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


相关文章
|
1月前
|
C# Windows
C#通过代码实现快捷键编辑
C#通过代码实现快捷键编辑
|
3月前
|
开发框架 .NET 编译器
C# 10.0中Lambda表达式的改进:更简洁、更灵活的代码编写体验
【1月更文挑战第21天】随着C#语言的不断发展,Lambda表达式作为一种简洁、高效的函数式编程工具,在C# 10.0中迎来了重要的改进。本文将详细探讨C# 10.0中Lambda表达式的新特性,包括参数类型的推断增强、自然类型的Lambda参数以及Lambda表达式的属性改进等。这些改进不仅简化了Lambda表达式的编写过程,还提升了代码的可读性和灵活性,为开发者带来了更优质的编程体验。
|
3月前
|
C# 开发者
C# 10.0中的文件范围命名空间:简化代码组织的新方式
【1月更文挑战第18天】C# 10.0引入了文件范围的命名空间,这是一种新的语法糖,用于更简洁地组织和管理代码。文件范围命名空间允许开发者在每个文件的基础上定义命名空间,而无需显式使用花括号包裹整个文件内容。本文将深入探讨文件范围命名空间的工作原理、使用场景以及它们为C#开发者带来的便利。
|
4月前
|
存储 人工智能 C#
【Unity 3D】C#中数组、集合、栈、队列、哈希表、字典的讲解(附测试代码)
【Unity 3D】C#中数组、集合、栈、队列、哈希表、字典的讲解(附测试代码)
36 0
|
5月前
|
开发框架 .NET C#
如何调试 C# Emit 生成的动态代码?
如何调试 C# Emit 生成的动态代码?
|
4月前
|
IDE C# 开发工具
C# | 多线程批量下载文件(创建N个线程同时批量下载文件,只需要几行代码而已)
批量下载文件时使用多线程可以有效缩短完成时间,本文将讲解如何使用C#+CodePlus扩展库快速完成多线程的文件下载。 大部分代码由IDE自动生成,需要我们自己编写的代码正好**10行**。也就是说,只需要10分钟,就可以手撸一个多线程的批量下载器。
86 0
C# | 多线程批量下载文件(创建N个线程同时批量下载文件,只需要几行代码而已)
|
2月前
|
数据采集 JSON 前端开发
从代码到内容:使用C#和Fizzler探索Instagram的深处
Instagram是一个流行的社交媒体平台,拥有数亿的用户和海量的图片和视频内容。如果您想要从Instagram上获取一些有用的信息或数据,您可能需要使用爬虫技术来自动化地抓取和分析网页内容。本文将介绍如何使用C#和Fizzler这两个强大的工具,来实现一个简单而高效的Instagram爬虫,从代码到内容,探索Instagram的深处。
|
3月前
|
存储 传感器 监控
工业相机如何实现实时和本地Raw格式图像和Bitmap格式图像的保存和相互转换(C#代码,UI界面版)
工业相机如何实现实时和本地Raw格式图像和Bitmap格式图像的保存和相互转换(C#代码,UI界面版)
31 0
|
3月前
|
存储 C# 容器
掌握 C# 变量:在代码中声明、初始化和使用不同类型的综合指南
变量是用于存储数据值的容器。 在 C# 中,有不同类型的变量(用不同的关键字定义),例如: int - 存储整数(没有小数点的整数),如 123 或 -123 double - 存储浮点数,有小数点,如 19.99 或 -19.99 char - 存储单个字符,如 'a' 或 'B'。Char 值用单引号括起来 string - 存储文本,如 "Hello World"。String 值用双引号括起来 bool - 存储具有两个状态的值:true 或 false
37 2
|
8月前
|
存储 C# 图形学
代码解析 C# 引用类型还是值类型
代码解析 C# 引用类型还是值类型