文档章节

给 c# 程序员的十个重要提示

酱哥哥
 酱哥哥
发布于 2014/08/05 16:47
字数 1268
阅读 157
收藏 18

本文讲述我认为对 c# 程序员最重要的 10 个提示, 每个提示都会有一段对应的代码, 对 新手来说也很容易掌握。

1: 为非公开的方法编写测试

你尝试过为组件的非公开方法写测试么? 很多开发者都没有写过, 因为这些方法对测试项 目来说是不可见的。 c# 可以通过在AssemblyInfo.cs 中添加下面的标记 (InternalsVisibleToAttribute) , 让内部成员对其它组件可见。

//Make the internals visible to the test assembly
[assembly: InternalsVisibleTo( "MyTestAssembly" )]



2: 使用 Tuples 类型

public Tuple< int , string , string > GetEmployee() {
     int employeeId = 1001;
     string firstName = "Rudy" ;
     string lastName = "Koertson" ;
 
     //Create a tuple and return
     return Tuple.Create(employeeId, firstName, lastName);
}


3: 用 yield 替代临时集合

从集合中选出部分成员时, 通常会创建一个临时集合/列表来保存成员并返回, 例如下面 的代码:

public List< int > GetValuesGreaterThan100(List< int > masterCollection) {
     List< int > tempResult = new List< int >();
 
     foreach (var value in masterCollection) {
         if (value > 100) {
             tempResult.Add(value);
         }
     }
     return tempResult;
}


要避免这样的临时集合, 可以使用 yield 关键字, 示例如下:

public IEnumerable< int > GetValuesGreaterThan100(List< int > masterCollection) {
     foreach (var value in masterCollection) {
         if (value > 100) {
             yield return value;
         }
     }
}


当然, 也可是使用 LINQ 来解决上面的问题。

4: 告诉别人你将替换一个方法

当你有一个组件时, 并且你打算替换其中的一个方法时, 可以先为方法添加过时标记以通 知客户端, 示例代码如下:

[Obsolete( "This method will be deprecated soon. You could use XYZ alternatively." )]
public void MyComponentLegacyMethod() {
     //Here is the implementation
}


使用这个方法客户端在编译时会发出一个警告, 如果你不再允许客户端使用过时的方法时, 可以为过时标记添加一个额外的布尔参数, 在下面的例子中, 客户但程序将编译失败:

[Obsolete( "This method is deprecated. You could use XYZ alternatively." , true )]
public void MyComponentLegacyMethod() {
     //Here is the implementation
}


5: 牢记 LINQ 查询是延迟执行的

在 .NET 中编写 LINQ 查询时, 只有当你访问 LINQ 查询的结果时, LINQ 查询才会被执 行, LINQ 的这种特征被称为延迟执行, 不过值得注意的是每访问一次结果, LINQ 查询 都会被执行一次。

为了避免重复 LINQ 查询的重复执行, 可以先将查询转换成列表, 如下所示:

public void MyComponentLegacyMethod(List< int > masterCollection) {
     // 在下面示例中, 如果没有调用 ToList , LINQ 查询将会被执行两次
     var result = masterCollection.Where(i => i > 100).ToList();
     Console.WriteLine(result.Count());
     Console.WriteLine(result.Average());
}


6: 使用 explicit 关键字转换业务实体类型

使用 explicit 关键字来定义业务实体类型之间的转换, 当代码中出现类型转换请求时, 转换方法会自动执行, 下面是示例代码:

class Program {
 
     static void Main( string [] args) {
         var entity = new ExternalEntity {
             Id = 1001,
             FirstName = "Dave" ,
             LastName = "Johnson"
         };
         var convertedEntity = (MyEntity)entity;
     }
}
 
class MyEntity {
 
     public int Id { get ; set ; }
     public string FullName { get ; set ; }
 
     public static explicit operator MyEntity(ExternalEntity externalEntity) {
         return new MyEntity {
             Id = externalEntity.Id,
             FullName = externalEntity.FirstName + " " + externalEntity.LastName
         };
     }
}
 
class ExternalEntity {
     public int Id { get ; set ; }
     public string FirstName { get ; set ; }
     public string LastName { get ; set ; }
}


7: 保持异常的原始堆栈跟踪

在 c# 代码中, 如果你像下面的代码一样在 catch 代码块中抛出 ConnectDatabase 方法中出现的异常, 异常的堆栈就会只显示到RunDataOperation 方法, 这样就会丢失 异常原始的堆栈跟踪信息导致不能找到确切的错误源头。

public void RunDataOperation() {
     try {
         Intialize();
         ConnectDatabase();
         Execute();
     }
     catch (Exception exception) {
         throw exception;
     }
}


保持原始堆栈跟踪的代码如下:

public void RunDataOperation() {
     try {
         Intialize();
         ConnectDatabase();
         Execute();
     }
     catch (Exception) {
         throw ;
     }
}


8: 使用 Flags 标记将枚举作为位域处理

在 c# 中为枚举类型添加 Flags 标记可以将枚举作为位域(即一组标志)处理, 这样可 以对枚举值进行自由组合, 示例代码如下:

class Program {
     static void Main( string [] args) {
         int snakes = 14;
         Console.WriteLine((Reptile)snakes);
     }
}
 
[Flags]
enum Reptile {
     BlackMamba = 2,
     CottonMouth = 4,
     Wiper = 8,
     Crocodile = 16,
     Aligator = 32
}


上面代码的输出为 “BlackMamba, CottonMouth, Wiper” , 如果没有 Flags 标记, 则上 面的输出为 14 。

9: 为泛型添加类型约束

创建泛型类型时, 需要指定提供的泛型类型必须实现指定的参数或者继承自特定的基类时, 可以这样做:

class MyGenricClass<T> where T : IMyInterface {
     //Body of the class come in here
}


当然, 也可以在方法级别这样做:

class MyGenricClass {
 
     public void MyGenericMethod<T>(T t) where T : IMyInterface {
         //Generic implementation goes in here
     }
 
}


10: IEnumerable 类型不能确保只读

在你创建的类型中, 暴露了一个类型为 IEnumerable 的只读属性, 但是调用者依然可 以通过类型转换来修改属性的内容, 比如这样:

class Program {
 
     static void Main( string [] args) {
         MyClass myClass = new MyClass();
         ((List< string >)myClass.ReadOnlyNameCollection).Add( "######From Client#####" );
 
         myClass.Print();
     }
}
 
class MyClass {
 
     List< string > _nameCollection = new List< string >();
 
     public MyClass() {
         _nameCollection.Add( "Rob" );
         _nameCollection.Add( "John" );
         _nameCollection.Add( "Jummy" );
         _nameCollection.Add( "Derek" );
     }
 
     public IEnumerable< string > ReadOnlyNameCollection {
         get { return _nameCollection.AsEnumerable(); }
     }
 
     public void Print() {
         foreach (var item in ReadOnlyNameCollection) {
             Console.WriteLine(item);
         }
     }
}


上面的代码修改了列表, 添加了一个新项目, 要避免这种情况, 应使用 AsReadOnly 而不是 AsEnumerable 

public IEnumerable< string > ReadOnlyNameCollection {
     get { return _nameCollection.AsReadOnly(); }
}


希望这些提示对你有用!

原文地址: Top 10 Tips for C# Programmers





本文转载自:http://beginor.github.io/2014/08/01/top-10-tips-for-c-programmers.html

酱哥哥
粉丝 27
博文 29
码字总数 10927
作品 0
合肥
高级程序员
私信 提问
“小明,滚出去!”之程序员版

西雅图IT圈:seattleit 【今日作者】littlelann 一个充满着人文情怀的 web前端相声演员 01我:我擅长C语言面试官:那你用C写个“Hello World”来看看我: 面试官:出去! 02 我:我擅长C# 面...

m68futkmurmtj
2017/11/09
0
0
8 个理由说明为什么 C# 是移动开发的最佳语言

编程语言流行度的数据已经将C#定为2012年度语言。他们的数据显示,C#在2012年增长了2.3个百分点,在同期比其它任何语言都要多。 是什么导致了C#在2012的增长呢?Windows 8的发布可能是个比较...

oschina
2013/01/03
12.7K
75
iBoxDB 2.8.3/2.17.3 发布,Java C# NoSQL 数据库

iBoxDB是一个实用高效的Java C#双核数据库,数据随时为可读状态,不受网络波动影响,不会出现连接突然断开或长时间等待导致几十秒的锁库。 内置的缓存层配合虚拟机的热点实时优化,访问次数越...

iBoxDB
2018/07/12
727
1
C# 5.0与VB.NET 有哪些新玩意

1,异步编程 因为在移动设备上,程序的响应速度实在是一个太重要的问题,所以对于应用被触摸后的反应也是同等重要。 在 Windows Runtime 中,设计师总是要考虑如果一个交互式操作需要耗费大于...

junwong
2012/08/16
4.4K
15
C# 5.0与VB.NET 有哪些新玩意

1,异步编程 因为在移动设备上,程序的响应速度实在是一个太重要的问题,所以对于应用被触摸后的反应也是同等重要。 在 Windows Runtime 中,设计师总是要考虑如果一个交互式操作需要耗费大于...

曾沙
2012/11/27
449
0

没有更多内容

加载失败,请刷新页面

加载更多

Spring Boot + Mybatis + Ehcache 二级缓存实例

二级缓存是多个SqlSession共享的,其作用域是mapper的同一个namespace,不同的sqlSession两次执行相同namespace下的sql语句且向sql中传递参数也相同即最终执行相同的sql语句,第一次执行完毕...

xiaolyuh
17分钟前
4
0
Spring源码学习(二)哎呦,按菜谱做菜与AbstractAutowireCapableBeanFactory.createBean流程差不多

记得跟老婆谈恋爱时,有一天心血来潮给老婆做饭,按照菜谱一步一步的做,结果差点把厨房烧了!!! 这事至今老婆还记得。 入口 上一篇说了,AbstractBeanFactory.getBean的主流程 ,今天来说下...

温安适
19分钟前
34
0
前端UI攻城狮 你们该抛弃jQuery了

你不再需要jQuery! Web工程师太依赖jQuery了,某种意义上说jQuery已经成了JavaScript的同义词。但是我们真的需要他么?或许我们应该反思一下什么时候才真的需要jQuery。 对我个人而言开始使...

前端老手
20分钟前
5
0
六、Java设计模式之工厂方法

工厂方法定义: 定义一个创建对象的接口,但让实现这个接口的类来决定实例化哪个类,工厂方法让类的实例化推迟到子类中进行 类型:创建型 工厂方法-使用场景: 创建对象需要大量重复的代码 ...

东风破2019
今天
5
0
win服务器管理遇到的一系列问题记录

有些小伙伴在使用iis7远程桌面管理工具的时候总是会遇到一系列的问题,下面就是为大家介绍一下服务器日常管理过程中出现的问题及我的解决办法和心得。希望能帮到大家。   拒绝服务器重新启...

1717197346
今天
6
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部