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

本文关键字:null 处理 错误 返回 float 方法 | 更新日期: 2023-09-27 18:12:51

我想在我的代码中添加一些错误处理。对于下面的例子,我想不出该怎么做:

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()方法中做其余的事情。这是一个好的实践吗?在这种情况下你会怎么做?

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

这段代码有两个问题,

首先抛出一个异常,然后是一个return——return语句永远不会被执行,因为异常会停止执行方法的其余部分,使得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为空是一个错误条件/异常情况,不应该发生,那么我会说抛出异常,并处理异常,如果在调用代码中抛出。

另一种方法是通过构造函数强制初始化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
    }
}

如果你抛出一个异常,返回语句将不会被执行,所以你尝试的正确版本应该是

  public float GetMaxX()
  {
      if(RawData == null)
      {
         throw new NullReferenceException();
      }
      //DO other stuff to find max X
      return MAX_X; //as float
   }

返回语句不会编译,因为float是一种值类型,它永远不会为空,除非你使用可空类型float?

我个人从你给的代码样本,我会抛出异常,因为你目前通过一个公共设置器暴露RawData对象,所以你不能保证它不会是空的,当GetMaxX被调用。然后异常可以在堆栈中传播并在任何级别被捕获,而通过使返回类型为空,您将不得不向调用代码添加额外的检查,以查看您的方法是否返回null并适当地处理。

我不清楚在错误的情况下你想做什么。是要抛出异常还是返回null?

一般来说,抛出异常是为了当调用者应该知道得更好,而你不想尝试恢复-让调用者清理混乱。

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

public float? GetMaxX()
如果你真的想在没有初始化的情况下爆炸,把RawData作为一个参数放在你的构造函数中。

可以删除throw异常语句下面的返回语句。每当抛出异常时,方法中不会执行任何其他语句(finally块是this的异常,但与此上下文中无关)。

除了这个关于函数的问题,我有一个关于RawData属性被公开访问的参数。一般来说,像那样打开一个收藏不是一个好主意。正如@sq33G所建议的,您可以通过将RawData作为构造函数参数传递来保证拥有一个有效的对象。当传入一个无效数组(null,可能大小为0 ?)时,您可能会在构造函数的早期失败。

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; }
}

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

在你的例子中,你可以

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