2011-11-01 29 views
1

我想在代碼中添加一些錯誤處理。我無法弄清楚如何做到這一點的下面的例子:如何爲'float method'返回null - 處理錯誤

public class DataPoints 
{ 
    public PointF[] RawData {get; set;} //raw measurement pairs 
    public float xMax; //max value on X axis 
    public float yMax; //max value on Y axis 

    public float GetMaxX() 
    { 
     if(RawData == null) 
     { 
      throw new NullReferenceException(); 
      return null; //THIS does not compile! I want to exit the method here 
     } 

    //DO other stuff to find max X 
    return MAX_X; //as float 
    } 
} 

這樣的想法是,我需要檢查,如果RawData已經設置然後做的東西休息GetMaxX()方法。這是一個很好的做法嗎?你會在這種情況下做什麼?

+0

如果你有興趣返回null,那麼去可空數據類型,這裏它期望你返回一個浮點值(null無效) – V4Vendetta

回答

4

有兩個問題與此代碼,

首先你拋出一個異常,然後恢復 - return語句將永遠不會被打的異常將停止該方法的其餘部分的執行,使返回語句變得多餘。

其次,返回類型爲float時不能返回null;你必須改變返回類型爲float? (參見:nullable types

因此,要麼,如果它是一個真正的錯誤情況下,有什麼你可以只用異常幹什麼去了:

public float GetMaxX() 
    { 
     if(RawData == null) 
      throw new NullReferenceException(); 

    //DO other stuff to find max X 
    return MAX_X; //as float 
    } 

或者,返回空落異常:

public float? GetMaxX() 
    { 
     if(RawData == null) 
      return null; 

    //DO other stuff to find max X 
    return MAX_X; //as float 
    } 

個人而言,如果RawData被空是一個錯誤條件/特殊情況應該不會發生,那麼我會說,拋出異常,如果扔在調用代碼來處理異常。

另一種方法是強制通過構造函數初始化RawData,使RawData私有(或至少是setter),並在那裏拋出異常。因爲它可以假設RawData以前將被設置,所以拋棄類中的任何其他邏輯來清除任何異常拋出/空值檢查。

沿着線的東西得到的:

public class DataPoints 
{ 
    private readonly PointF[] rawData; //raw measurement pairs 
    public float xMax; //max value on X axis 
    public float yMax; //max value on Y axis 

    public DataPoints(PointF[] rawData) 
    { 
     if (rawData == null) 
      throw new ArgumentNullException("rawData"); 

     this.rawData = rawData; 
    } 

    public float GetMaxX() 
    { 
     //DO other stuff to find max X 
     return MAX_X; //as float 
    } 
} 
2

如果你拋出一個異常return語句將不被執行的,所以你要嘗試什麼樣的正確版本將

public float GetMaxX() 
    { 
     if(RawData == null) 
     { 
     throw new NullReferenceException(); 
     } 

     //DO other stuff to find max X 
     return MAX_X; //as float 
    } 

return語句將無法編譯,因爲浮球是一個值除非使用可空類型float,否則永遠不能爲null?

個人從您給出的代碼示例中,我將拋出異常,因爲您當前通過公共setter暴露RawData對象,因此您不能保證在調用GetMaxX時它不會爲空。然後可以將異常傳播到堆棧並在任何級別捕獲,而通過使返回類型爲空,您將不得不向調用代碼添加額外的檢查,以查看您的方法是否已經返回null並適當地處理。

1

我不是你想在錯誤的情況下做什麼明確的。你想拋出一個異常或返回null?

一般來說,拋出一個異常是因爲調用者應該知道的更好,並且你不想嘗試恢復 - 讓調用者清理混亂。

返回null表示調用者可能有一個很好的理由不初始化RawData,這對您的情況有意義。對於那些你需要有

public float? GetMaxX() 

如果你真的想沒事的時候被初始化炸燬,把RAWDATA在你的構造函數的參數。

1

您可以刪除拋出異常語句下面的return語句。每當引發異常時,在該方法中不會執行其他語句(最後,塊是例外情況,但在此情況下是不相關的)。

除了這個關於函數的問題,我有一個關於RawData屬性可以公開訪問的參數。打開這樣的集合通常不是一個好主意。正如@ sq33G所示,通過將RawData作爲構造函數參數傳遞,您可以保證擁有一個有效的對象。當傳遞一個無效的數組時,你可以在構造函數的早期失敗(null,可能大小爲零)。

private PointF[] _rawData; 

public DataPoints(PointF[] rawData) 
{ 
    if(rawData == null || rawData.Length == 0) 
     throw new ArgumentException("RawData should not be null and should contain at least one element"); 
    this._rawData = rawData; 
} 

如果這裏有必要說RawSata是從類的外部訪問,我建議你做的方式,無論是陣列本身(所以沒有setter),也可以對其內容進行修改。使用IEnumerable是一個正確的方法。

public IEnumerable<PointF> RawData 
{ 
    get { return _rawData; } 
} 
1

方法並不總是需要返回一個值;特別是,它也被允許通過拋出異常退出 (在這種情況下,沒有返回值)。您可以檢查規則 here

在你的榜樣,你既可以

(一)引發的NullReferenceException - 這將打破流動並返回

(B)返回默認值,如果RAWDATA是null - 這將打破流程並返回默認值。

float f() 
    { 
     if (RawData == null) 
     { 
      throw new NullReferenceException(); 
      return default(float); 
     } 
     return doOtherOperation(RawData); 
    } 

    float doOtherOperation(PointF[] RawData) 
    { 
     //do what you wanted to do 
     return default(float); 
    } 
相關問題