如何为'float方法'返回null - 错误处理

时间:2011-11-01 09:10:01

标签: c# exception exception-handling error-handling

我想在我的代码中加入一些错误处理。我无法弄清楚如何做以下示例:

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()方法中执行其余操作。这是一个很好的做法吗?在这种情况下你会做什么?

5 个答案:

答案 0 :(得分:5)

此代码存在两个问题,

首先你要抛出异常,然后返回 - 返回语句永远不会被命中,因为异常会停止执行方法的其余部分,使得return语句变得多余。

其次,当返回类型为float时,不能返回null;你必须改变返回类型是浮动的吗? (见:nullable types

所以要么,如果这是一个真正的错误案例,因为没有什么可以做的只是例外:

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

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

或者,返回null并删除异常:

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

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

就个人而言,如果RawData为null是一个错误条件/异常情况应该永远不会发生,那么我会说抛出异常,并在调用代码中抛出异常处理。

另一种方法是强制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
    }
}

答案 1 :(得分: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是一个值类型,除非你使用可空类型float,否则它永远不会为null?

从您给出的代码示例中我个人抛出异常,因为您当前通过公共setter公开RawData对象,因此您无法保证在调用GetMaxX时它不会为null。然后异常可以在堆栈中向上传播并在任何级别捕获,而通过使返回类型为空,您将不得不向调用代码添加额外的检查,以查看您的方法是否返回null并正确处理。

答案 2 :(得分:1)

我不清楚在发生错误时你想做什么。您要抛出异常还是返回null?

一般来说,抛出异常是因为调用者应该知道更好并且您不想尝试恢复 - 让调用者清理混乱。

返回null是指调用者可能有充分的理由不初始化RawData,这在您的情况下是有意义的。为此你需要

public float? GetMaxX()

如果你真的想在没有初始化时爆炸,请将RawData作为参数放在你的构造函数中。

答案 3 :(得分:1)

您可以删除throw异常语句下面的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; }
}

答案 4 :(得分:1)

并不总是需要一个方法来返回一个值;特别是,它也被允许退出 通过抛出异常(在这种情况下不返回任何值)。您可以检查规则 here

在您的示例中,您可以

(a)引发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);
    }