【问题标题】:needs overload operator< and null check需要重载 operator< 和 null 检查
【发布时间】:2012-03-25 23:39:18
【问题描述】:

我在 c# 中重载了小于运算符,我想知道这是否需要检查 null。您可以在下面找到一个示例:

public static bool operator <(MyClass x, MyClass y)
{
  if (x == null && y == null)
  {
    return false;
  }
  if (x == null)
  {
    return true; //false?
  }
  if (y == null)
  {
    return false; //true?
  }
  return x.Value < y.Value;
}

或者这是正确的:

public static bool operator <(MyClass x, MyClass y)
{
  return x.Value < y.Value;
}

我没有找到任何关于此的说明。但也许我错过了什么。

【问题讨论】:

    标签: c# operator-overloading


    【解决方案1】:

    自定义运算符只不过是一种静态方法。此外,一般的运算符通常不应该抛出异常。这意味着如果 MyClass 是引用类型,您需要这些空检查。

    顺便说一句,nulls 小于非nulls 是常规的,这使得您提出的实现具有惯用性。

    【讨论】:

    • 第一个参数怎么可以为空?
    • 或者你只是让系统抛出,没有什么坏处(除了例外稍微不太合适)。
    • @vulkanino:第一个参数可以为空,因为操作符是作为静态方法实现的。
    • @vulkanino MyClass a = null;我的类 b = null;返回一个
    【解决方案2】:

    如果xynull,我个人会抛出ArgumentNullException,这应该是一个例外情况。

    【讨论】:

    • NullReferenceException 不应从用户代码中抛出,这意味着存在编程错误。请改用ArgumentNullException
    • @asawyer ArgumentNullException 也表示一个编程错误。我不确定同时拥有这两个框架是否是一个如此明智的决定。
    • @Konrad:文档说“将空引用(Visual Basic 中的无)传递给不接受它作为有效参数的方法时引发的异常。”对于ArgumentNullException,但“尝试取消引用空对象引用时引发的异常。”对于NullReferenceException,所以我认为前者更合适。
    • 如果将 null 传递到引用类型比较中,则在调用代码中存在一个编程错误。通常(总是?)比较空引用类型的大小是没有意义的——否则你会如何响应这个错误?
    • @mdm 区别是人为的和任意的。从逻辑上讲,将空对象传递给不期望它的方法等于取消引用空指针。唯一的有意义的区别发生在方法真的没有取消引用的情况下(但我很难想到这样的例子,除非在存储值时)。我认为 .NET 框架设计者不应该为此引入两个单独的例外。
    【解决方案3】:

    答案取决于您的预期使用模式。如果您打算混合使用空值,并且您希望将 null 值小于非空值,那么您的实现是正确的;如果您想考虑null 值大于非空对象,则应使用注释掉的返回值(falsetrue)。如果您不打算在混合中允许空值,则抛出 ArgumentNullException 或允许 NullReferenceException 将是正确的选择。

    【讨论】:

    • ArgumentNullException 孩子,永远不要故意扔NullReferenceException
    • 这是“我打算这样做”和“哎呀”之间的区别。
    【解决方案4】:

    两种方法都是正确的(对于不同的正确值)。

    如果 xy 可能为 null 并且在您的情况下具有有效含义,则使用第一种方法。

    如果xy 极不可能为null,则使用第二个,让任何异常传播到调用代码进行处理。

    【讨论】:

      【解决方案5】:
      1. 在类上重载运算符是个坏主意。不过对于结构来说没问题。

      2. 如果您决定在类上重载运算符,则必须:
        一种。在您的逻辑中包含空检查
        湾。传入null时抛出异常
        C。不要空检查并允许 NullReferenceExceptions(坏)

      基本上,在类上重载运算符是个坏主意。我要么把你的类变成一个结构,要么只实现一个接口,比如IComparable&lt;T&gt;/IEquatable&lt;T&gt;,它在比较中使用空值时有指导方针。

      【讨论】:

      • 我不同意这一点——拥有类似值的类通常是有意义的,特别是因为 .NET 中的相关(有用)指南说“如果有疑问,请编写一个类”。
      • 为一个类重载运算符是一个更糟糕的主意。结构是一个值,可以与其他值进行比较。类是一个引用,不应被视为结构。我还没有看到任何需要为类(而不是结构)重载运算符。
      • 标准示例:复杂类。你不会超载运算符吗?
      • 我也不同意,请参阅 System.Version。这是一门课,我认为 , ... 很有用而且很有意义。
      • @m-y 重载运算符是否有逻辑原因:当它对业务实体有意义时,你重载它们。另一方面,是否使用类或结构不是业务决策,而是基于技术权衡的技术决策。这两个决定(在某种程度上)是正交的。例如,为什么不为 String 类重载比较运算符?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-30
      • 2011-06-01
      • 2014-04-25
      相关资源
      最近更新 更多