基于不要返回null之EmptyFactory的應用詳解
更新時間:2013年05月13日 17:32:52 作者:
本篇文章對不要返回null之EmptyFactory進行了詳細的分析介紹,需要的朋友參考下
有很多書上都提出過一個建議:不要返回null對象。
比如下面的GetUsers方法:
public class User
{
public string Id { get; set; }
public string Name { get; set; }
}
public List<User> GetUsers()
{
List<User> result = new List<User>();
// search db for user
return result;
}
如果其他方法由GetUsersOfxxx,GetUsersByXXX之類的方法,那么就有大量
List<User> result = new List<User>();
考慮到這一點,可以將new List<User>() 封裝到方法中,這就是”工廠”模式了.
因為可能不是List<User> ,也許是Stack<User> 更或者是ObservableCollection<User>
所以配合泛型,代碼如下:
public static class EmptyFactory
{
public static T Empty<T>() where T : IEnumerable, new()
{
return new T();
}
}
使用如下:
List<string> emptyList = new List<string>();
Stack<string> emptyStack = new Stack<string>();
ObservableCollection<string> emptyObserable = new ObservableCollection<string>();
emptyList = EmptyFactory.Empty<List<string>>();
emptyStack = EmptyFactory.Empty<Stack<string>>();
emptyObserable = EmptyFactory.Empty<ObservableCollection<string>>();
雖然這樣寫可以滿足要求,但是可以發(fā)現(xiàn)基本沒什么好處,寫EmptyFactory還不如new 來得快。
不過如果能夠緩存對象的話,也許EmptyFactory有作用。
考慮到這一點,為EmptyFactory增加緩存機制的代碼如下,使用Dictionary<Type,Object> 來實現(xiàn)
public static class EmptyFactory
{
private static Dictionary<Type, object> cacheEmptyObjects =
new Dictionary<Type, object>();
public static T Empty<T>() where T : IEnumerable, new()
{
Type genericType = typeof(T);
if (cacheEmptyObjects.ContainsKey(genericType))
{
return (T)cacheEmptyObjects[genericType];
}
else
{
T tempEmptyObject = new T();
cacheEmptyObjects.Add(genericType, tempEmptyObject);
return tempEmptyObject;
}
}
}
測試代碼如下:
public static class EmptyFactory<T> where T : IEnumerable, new()
{
private static Dictionary<Type, T> cacheEmptyObjects = new Dictionary<Type, T>();
public static T Empty()
{
Type genericType = typeof(T);
if (cacheEmptyObjects.ContainsKey(genericType))
{
return cacheEmptyObjects[genericType];
}
else
{
T tempEmptyObject = new T();
cacheEmptyObjects.Add(genericType, tempEmptyObject);
return tempEmptyObject;
}
}
}
使用的時候,只需要
比如下面的GetUsers方法:
public class User
{
public string Id { get; set; }
public string Name { get; set; }
}
public List<User> GetUsers()
{
List<User> result = new List<User>();
// search db for user
return result;
}
如果其他方法由GetUsersOfxxx,GetUsersByXXX之類的方法,那么就有大量
List<User> result = new List<User>();
考慮到這一點,可以將new List<User>() 封裝到方法中,這就是”工廠”模式了.
因為可能不是List<User> ,也許是Stack<User> 更或者是ObservableCollection<User>
所以配合泛型,代碼如下:
public static class EmptyFactory
{
public static T Empty<T>() where T : IEnumerable, new()
{
return new T();
}
}
使用如下:
List<string> emptyList = new List<string>();
Stack<string> emptyStack = new Stack<string>();
ObservableCollection<string> emptyObserable = new ObservableCollection<string>();
emptyList = EmptyFactory.Empty<List<string>>();
emptyStack = EmptyFactory.Empty<Stack<string>>();
emptyObserable = EmptyFactory.Empty<ObservableCollection<string>>();
雖然這樣寫可以滿足要求,但是可以發(fā)現(xiàn)基本沒什么好處,寫EmptyFactory還不如new 來得快。
不過如果能夠緩存對象的話,也許EmptyFactory有作用。
考慮到這一點,為EmptyFactory增加緩存機制的代碼如下,使用Dictionary<Type,Object> 來實現(xiàn)
復制代碼 代碼如下:
public static class EmptyFactory
{
private static Dictionary<Type, object> cacheEmptyObjects =
new Dictionary<Type, object>();
public static T Empty<T>() where T : IEnumerable, new()
{
Type genericType = typeof(T);
if (cacheEmptyObjects.ContainsKey(genericType))
{
return (T)cacheEmptyObjects[genericType];
}
else
{
T tempEmptyObject = new T();
cacheEmptyObjects.Add(genericType, tempEmptyObject);
return tempEmptyObject;
}
}
}
測試代碼如下:
不過這種方法有一個缺陷,對于值類型而言,需要裝箱。
其根本原因是因為EmptyFactory不知道T是什么,如果EmptyFactory知道T的話,那么就可以使用Dictionary<T,T> 的緩存了。
解決這個問題的思路是將EmptyFactory變成泛型類:
代碼如下:
復制代碼 代碼如下:
public static class EmptyFactory<T> where T : IEnumerable, new()
{
private static Dictionary<Type, T> cacheEmptyObjects = new Dictionary<Type, T>();
public static T Empty()
{
Type genericType = typeof(T);
if (cacheEmptyObjects.ContainsKey(genericType))
{
return cacheEmptyObjects[genericType];
}
else
{
T tempEmptyObject = new T();
cacheEmptyObjects.Add(genericType, tempEmptyObject);
return tempEmptyObject;
}
}
}
使用的時候,只需要
當然也可以EmptyFactory<List<User>>.Empty();
為什么不用Enumersble.Empty<T>方法呢?
因為Enumerable.Empty<T> 返回的是IEnumerable<T>對象。
相關文章
C# 中將數(shù)值型數(shù)據(jù)轉換為字節(jié)數(shù)組的方法
C# 中將數(shù)值型數(shù)據(jù)轉換為字節(jié)數(shù)組的方法,需要的朋友可以參考一下2013-05-05C#中String和StringBuilder的簡介與區(qū)別
今天小編就為大家分享一篇關于C#中String和StringBuilder的簡介與區(qū)別,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧2018-10-10