【設計原則和建議】 方法輸入參數
個人在多年的開發中對設計有一些自己的想法,在此總結出一些規則希望和大家共同探討
當然很多設計大家應該已經知道了,當然對于某些設計可能每個人有不同的看法
本系列文章不是為了討論基本的語法,而是介紹和討論一些設計的規則
1.在允許的情況下,優先使用父類作為參數類型
其好處是允許該函數有更大的適用范圍,有更多的第三方可以調用該方法 (原來持有父類和其他子類變量的第三方現在也可以調用了)
(可別為了更大的參數范圍把變量都聲明為Object了)
class InputParameter
{
//如果可以 參數類型優先選擇父類
public void Method1(IEnumerable<string> p)//good
{
}
public void Method1(List<string> p)//bad
{
}
}
2.如果該方法是公開方法,那么建議檢查輸入參數是否有效
其好處是,函數不會拋出莫名其妙的“為將對象引用到設置對象的實例” (現在獲得的是更準確的信息)
{
public void Method1(string userName)
{
if (userName == null)
{
throw new ArgumentNullException("userName");
}
//在使用userName之前最好進行檢查,userName的值是否合法
}
}
3.如果輸入參數不合法,建議終止當前執行并拋出異常
(代碼如上圖所示)既然輸入參數非法,那么一定要停止程序的執行,以免在錯誤的道路上越走越遠:)
class InputParameter
{
public void Method1(string userName)
{
if (userName == null)
{
throw new ArgumentNullException("userName");
}
if (userName.Length <= 5)
{
throw new ArgumentOutOfRangeException("userName", "userName 必須大于5個字符");
}
//在使用userName之前最好進行檢查,userName的值是否合法
}
}
4.如果可以,參數類型要盡可能的準確
準確的參數類型有利于用戶知道調用規則 以下面兩個例子
如果是string 格式的時間,那么用戶就猜不到時間格式了 (時間格式和當前線程的區域有關,也許是 yyyy-MM-dd 也許是 dd/MM/yyyy)
換成DateTime就不會傳入錯誤的時間格式了
class InputParameter
{
public void Method1(Guid id)//good
{
}
public void Method1(string id)//bad
{
}
public void Method2(DateTime createdTime)//good
{
}
public void Method2(string createdTime)//bad
{
}
}
5.在有重載的時候,最好保證參數順序
好處就是調用的時候方便,開發這邊也方便
class InputParameter
{
public void Method1(Guid id)
{
}
public void Method1(Guid id, int type)//good
{
}
public void Method1(int type, Guid id)//bad
{
}
}
6.如果有params參數,那么把它放在最后
7.適當使用默認參數,可以減少開發的成本
public void Method1(Guid id, int type = 1)
{
}
8.參數名字個人有個人的標準,我個人推薦駱駝命名法
9.移除一切沒有被用到的參數,不要為了以后的擴展預留參數,因為通過重構添加參數的方式是很方便的
10.如果可以,避免使用ref和out參數
原因是含有ref和out參數的方法較難和其他方法協作,集成'而且某些不了解該參數行為的人可能會誤用該方法;為了更好的設計,建議是不要使用ref和out
也不是完全禁止ref和out,有的時候為了性能原因還是會使用ref和out,以下就是一個例子
string s = "123";
int i = 0;
int.TryParse(s,out i);//性能很好,判斷字符串是否合法的代碼也簡單
i = int.Parse(s);//沒有發生異常的時候沒啥問題....
11.如果有若干個同類型同含義對象,建議使用params參數
public class BadRepeatArguments
{
// Violates rule: ReplaceRepetitiveArgumentsWithParamsArray.
public void VariableArguments(object obj1, object obj2, object obj3, object obj4) {}
public void VariableArguments(object obj1, object obj2, object obj3, object obj4, object obj5) {}
}
public class GoodRepeatArguments
{
public void VariableArguments(object obj1) {}
public void VariableArguments(object obj1, object obj2) {}
public void VariableArguments(object obj1, object obj2, object obj3) {}
public void VariableArguments(params Object[] arg) {}
}
如果你想通過某種方式把參數傳遞到函數內,可是因為種種原因又不能修改方法簽名,那么可以采用以下方法
- 第三方類的靜態成員,包括Session Cache等
- 如果現有參數類型是類或者結構體,可以直接修改它
- CallContext (該做法不會影響到現有類定義,也不會因為把數據放在共享空間導致沖突)
參考以下代碼
class InputParameter
{
public void Method1()
{
CallContext.LogicalSetData("parameter1", DateTime.Now);
Method2();
}
public void Method2()
{
var createdTime = Convert.ToDateTime(CallContext.LogicalGetData("parameter1"));
}
}
許多內容引用自MSDN,FxCop 和其他第三方文章..
因為本人水平有限,如有遺漏或謬誤,還請各位高手指正
浙公網安備 33010602011771號