2011-05-07 46 views
5

我在我的項目中使用泛型屬性,但我不知道,是否有任何缺點使用它們,請告訴我一個場景,它們有一個缺點?我的代碼如下。通用屬性的缺點?

public class GenericResult<T> 
{ 
    public T Data { get; set; } 
    public bool IsSuccess { get; set; } 
    public string Message { get; set; } 
} 

public GenericResult<int> AddCategory(TCategory tCategory) 
{ 
    GenericResult<int> result = new GenericResult<int>(); 

    //business logic validation,dont make sense,only example :) 
    if (tCategory.Name.Lenght > 100) 
    { 
     result.IsSuccess = false; 
     result.Message = "Category Name length is too long"; 
     result.Data = 0; 
    } 

    //handle .net runtime error//may be database is not aviable. 
    try 
    { 
     result.Data = this.catalogRepository.AddCategory(tCategory); 
     result.IsSuccess = true; 
    } 
    catch (Exception ex) 
    { 
     result.Data = 0; 
     result.IsSuccess = false; 
     result.Message = ex.Message; 
    } 
    return result; 
} 

public GenericResult<IEnumerable<TCategory>> GetCategoryHierarchy(TCategory parentCategory) 
{ 
    GenericResult<IEnumerable<TCategory>> result = new GenericResult<IEnumerable<TCategory>>(); 
    try 
    { 
     IEnumerable<TCategory> allCategories = catalogRepository.GetAllCategories(); 
     result.Data = GetCategoryHierarchy(allCategories, parentCategory); 
     result.IsSuccess = true; 

    } 
    catch (Exception ex) 
    { 
     result.IsSuccess = false; 
     result.Data = null; 
     result.Message = ex.Message; 
    } 
    return result; 
} 
+0

如果AddCategory失敗了,你爲什麼要返回一個實例?這通常被認爲是不好的做法。返回null使外部清晰可見某些失敗。 – 2011-05-07 07:28:06

+0

同意馬里奧,但拋出一個異常可能會更具表現力,以顯示每個人出現問題! – renatoargh 2011-05-07 07:35:46

+1

'null'不會給你留言。他回來的是一個'MayBe '的自制版本,這是其他語言的良好模式。 – CodesInChaos 2011-05-07 07:37:17

回答

4

如果你不想扔掉一個例外,但更喜歡返回一個包含錯誤或值的結果,例如MayBe在某些情況下很好。但說實話,在這種情況下,我寧願簡單地拋出/傳遞異常。

我寧願返回一個不可變的結構作爲MayBe而不是像你這樣的可變類。它與Nullable<T>非常相似,只是它適用於引用類型並可以存儲錯誤。喜歡的東西:

public struct MayBe<T> 
{ 
    private T value; 
    private Exception error; 

    public bool HasValue{get{return error==null;}} 
    public T Value 
    { 
     if(error!=null) 
     throw error; 
     else 
     return value; 
    } 

    public static MayBe<T> CreateError(Exception exception) 
    { 
     return new MayBe<T>(default(T),exception); 
    } 

    public static MayBe<T> CreateValue(T value) 
    { 
     return new MayBe<T>(value,null); 
    } 

    public static implicit operator MayBe<T>(T value) 
    { 
     return CreateValue(value); 
    } 

    public override string ToString() 
    { 
     if(HasValue) 
      return "Value: "+Value.ToString(); 
     else 
      return "Error: "+Error.GetType().Name+" "+Error.Message; 
    } 
} 

你的代碼變得

public MayBe<int> AddCategory(TCategory tCategory) 
{ 
    try 
    { 
     return this.catalogRepository.AddCategory(tCategory); 
    } 
    catch (Exception ex) 
    { 
     return MayBe<int>.CreateError(ex); 
    } 

    return result; 
} 

public MayBe<IEnumerable<TCategory>> GetCategoryHierarchy(TCategory parentCategory) 
{ 
    try 
    { 
     IEnumerable<TCategory> allCategories = catalogRepository.GetAllCategories(); 
     return allCategories; 

    } 
    catch (Exception ex) 
    { 
     return MayBe<int>.CreateError(ex); 
    } 

    return result; 
} 

一個問題,我這個執行看到的是,異常不是完全不可改變的。如果在多個線程上引發相同的MayBe<T>,則會導致問題。也許有人可以建議更好的實施。

+0

爲什麼'struct'?(只是好奇) – abatishchev 2011-05-07 08:13:12

+0

因爲1)它不能是null。由於我們已經在內部處理'null'值,所以'MayBe'爲'null'沒有多大意義2)它很便宜。它只有兩個字段。 3)由於它是不可變的,除了可空性之外幾乎沒有語義差異。 – CodesInChaos 2011-05-07 08:24:07

0

使用自動屬性是相當好的,我沒有看到任何問題。

但我強烈譴責使用類的模式,結果告訴外界失敗。返回null或在發生嚴重失敗時拋出異常。

心連心

馬里奧

+1

返回'null'會清除錯誤信息,並且在某些情況下拋出異常可能會很慢或很煩人。特別是在函數式編程。 – CodesInChaos 2011-05-07 08:01:17

4

我寧願刪除IsSuccessMessage,只返回對象。見下面...

看看我的問題Good practices when handling Exceptions in C#。你正在返回錯誤而不是拋出異常,並在.NET中,這是不建議。

From MSDN

不要返回錯誤代碼。例外情況是報告框架錯誤的主要方式。


你在做什麼,建議在一些文章/書我讀過,包括The Pragmatic Programmer: From Journeyman to Masterthis Joel Spolsky article,而是通過MSDN如說,在.NET例外是一種更合理的。

編輯:
如果你仍然想這樣做的(即使可以帶來一些問題與您的代碼的開發人員),我認爲,在一般情況下,它可能是一個好辦法。事實上,我將編輯我在這個答案掛鉤的問題放置一個鏈接到你的代碼返回錯誤而不是在.NET拋出異常的替代

+0

但我不想唯一的例外handlings,我要讓我的方便操作的驗證,我已經編輯我的問題類似下面 如果(tCategory.Name == NULL){ result.IsSuccess = FALSE; result.Message =「類別名稱不能爲空」; result.Data = 0; } – tobias 2011-05-07 08:02:04

+0

@tobias有什麼和做之間的區別是:'拋出新的ArgumentNullException(「類別名稱不能爲空」);'或'只是拋出新的ArgumentNullException(「t類別」);'?我的意思是,你仍然可以驗證並告訴對方有什麼錯誤... – 2011-05-07 08:04:16

+0

並不總是正確的,想象一下你正在建設一個UI框架或設置的東西,一個界面內工作,如果你簡單地拋出一個異常,默認的UI框架可能無法執行自己的待處理任務。當你不想用異常打擾底層框架並以不同的方式執行你的任務時,這種模式在哪裏還是有用的。 – 2011-05-07 08:05:04

2

如果您的應用範圍是完全內部.NET範圍,那麼這種模式是沒有用的,只是如其他人所說的,你應該讓異常被拋出,你可能要更改的例外。

但是,如果你的應用範圍較廣,可能包括任何其他客戶端框架,可能通過JSON,Web服務等,如果客戶端框架不正確地支持例外那麼這種模式可能是有用的。例如,在基於JSON的Javascript調用中,您總是會得到一個結果,並顯示一條消息,指示服務器端是否出現故障。客戶端的故障可能是服務器端故障或網絡故障,通常所有的客戶端框架都會檢測到並且只報告網絡故障和不正確的編碼框架會導致混亂,因爲當客戶端沒有收到錯誤報告時,服務器端。

另外一個地方,這種模式非常有用的是,當你在UI中編寫一些插件或者在別人的框架內部拋出異常可能會導致不希望的結果,因爲異常之後,第三方框架可能會說「意外錯誤「因爲他們不這樣做,他們沒有理解你的例外。這種模式在處於別人的框架內時非常有用,並且無論您的失敗如何,仍然可以讓底層框架正常工作。你可能可以在你的應用程序框架內正確地進行通信

我最近看到,它仍然是一個錯誤,停止WPF如果您設定的網址,並且不存在圖像的源處理一些未決的UI相關的活動。您將看到跟蹤的網絡相關異常,但WPF將不完全停止處理任何處於待處理任務狀態的應用程序,應用程序仍然可以正常工作,但它確實會影響其他應用程序不應該使用的其他UI元素。

+0

類似的模式在函數式編程中非常有用。 – CodesInChaos 2011-05-07 08:00:11