給 c# 程序員的十個重要提示

本文講述我認爲對 c# 程序員最重要的 10 個提示, 每一個提示都會有一段對應的代碼, 對 新手來講也很容易掌握。html

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 替代臨時集合

從集合中選出部分紅員時, 一般會建立一個臨時集合/列表來保存成員並返回, 例以下面 的代碼:
c#

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 來解決上面的問題。spa

4: 告訴別人你將替換一個方法

當你有一個組件時, 而且你打算替換其中的一個方法時, 能夠先爲方法添加過期標記以通 知客戶端, 示例代碼以下:code

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


使用這個方法客戶端在編譯時會發出一個警告, 若是你再也不容許客戶端使用過期的方法時, 能夠爲過期標記添加一個額外的布爾參數, 在下面的例子中, 客戶但程序將編譯失敗:orm

[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 查詢 都會被執行一次。htm

爲了不重複 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 關鍵字來定義業務實體類型之間的轉換, 當代碼中出現類型轉換請求時, 轉換方法會自動執行, 下面是示例代碼:ip

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

相關文章
相關標籤/搜索