运算符重载和不同类型

时间:2011-08-14 03:51:57

标签: c#

我有一个课程分数,它将大量用于与整数的比较。我打算重载==运算符以根据下面的代码进行这些比较?

public class Score
{
    public Score(int score) {
        Value = score;
    }

    public static bool operator ==(Score x, int y) {
        return x != null && x.Value == y;
    }

    public static bool operator ==(int y, Score x)
    {
        return x != null && x.Value == y;
    }
}

这是运算符重载的明智用法吗?

我是否应该为操作员的LH和RH侧提供过载以允许使用对称?

5 个答案:

答案 0 :(得分:9)

我可以继续定义从intScore的隐式转换,这样当你处理相等时,你只需要处理一种类型。

public static implicit operator Score(int value)
{
    return new Score { Value = value }; // or new Score(value);
}
// define bool operator ==(Score score1, Score score2)

// elsewhere 
Score score = new Score { Value = 1 };
bool isScoreOne = (score == 1);

在您定义自己的==运算符时,请务必继续定义!=,并覆盖EqualsGetHashCode

答案 1 :(得分:4)

我认为使用运算符重载是一种奇怪的情况,但这是你的调用。

但是,我的主要观点是,如果你重载==你也需要超载!=

如果你然后重载!=,比较x并使用x != null检查它不为空的部分将导致==运算符调用!=运算符。这本身不是问题,只要这不会使用==比较,因为你将有一个递归的调用集,导致堆栈溢出。

然而,由于很多人在重载时!=将其实现为'not ==' - 在您的情况下,这将导致堆栈溢出。

解决方案:特别是在重载==,!=和Equals()时,最好在与null比较时使用Object.ReferenceEquals(x, null);

答案 2 :(得分:3)

通常当我看到一个重载的运算符时,它会将该类与自身进行比较。因此,如果您有多个实例变量,您将弄清楚如何比较两者以确定某些内容是否相等,更大,更少等。

我不明白为什么你不这样做:

if(myScore.value == 5)
{
 //do stuff
}

答案 3 :(得分:2)

“这是运算符重载的明智用法吗?”

如果它使您的代码更容易理解并且不会导致问题,我会说,是的,绝对!可能还有其他方法,但如果这对你有用,我看不出问题。

“我是否应该为操作员的LH和RH侧提供过载以允许使用对称?”

我认为,除非你有特定的理由这样做,换句话说,如果你正在使用或需要它们,那么你就不会需要它。 (YAGNI)我看到的唯一真正的例外是,如果你正在编写一个框架,你可以很好地了解别人会需要它。

答案 4 :(得分:0)

tl; dr 在宏伟的计划中;不,这不是一个明智的想法。

  1. 一个人觉得有必要提出或搜索这个问题的事实已经说明了。
  2. 很少有人关心的事实表明,可能有一种方法可以简单地避免你需要提出问题的情况。
  3. 最后两点至少应该迫使你重新考虑一些事情,不管他们可能似乎无关。
  4. 考虑尽快在域逻辑之外为软件组件的所有输入分配类型。这样,我们通常称之为"域模型"永远不必担心这个。

    在您的情况下,这意味着将所有分数包装在Score个对象中。因为那是他们的本意。制作例外的需要总是至少可疑并且有资格作为代码气味。

    下一步是查看您的"域模型"没什么特别的 - 只是另一套模块。查看所有那些(通常是讨厌的)I / O接口,它们使用有形基元来履行不同/独立的角色。这自然(并且几乎神奇地)降低了所有组件(例如类)的个体复杂性。

    这样做的另一个副作用是你可能会发现这个问题变得毫无意义。 "如果我甚至不确定整数是分数,为什么我需要将分数与原始整数进行比较?如果我确定,为什么我之前没有说过(例如拳击它)?"

    更进一步,您可能会发现许多算法甚至不需要知道如何保留分数:它们中的大多数可能只需要能够比较它们才能看到如果它们相等或看哪个更高。我并不是说修改如何你保持分数的灵活性将来会有用,但作为一项规则如果它不重要那么那里& #39;不需要将代码绑定到实现只是为了可爱。也许令人惊讶的是,这也适用于诸如整数之类的原语,甚至是数字的概念(在所有你需要的情况下你不需要关心的是比较两个分数)。 SOLID原则提供了一个很好的指导,直到你可以为自己发展直觉。

    反击:人们总能提出表现论证来反对这种思路。根据我的经验,我发现JIT将优化和内联性能方面的任何内容(特别是对于平等比较等微不足道的事情),并且当它几乎不总是一种抽象性能关键的方法时代码以理智的方式。如果调度是一个问题,请不要犹豫密封您的类型。

    在测量并找到正确设计的瓶颈之后,无法通过另类但同样理智的设计来修复,那么人们需要诚实地说明他们遇到了< em>语言限制,在这种情况下,应该考虑提取代码并用更合适的语言编写代码,或者使用现有语言进行修改,但要对代码进行评论。

    总而言之,我提到我实际上完全按照您过去的建议行事,我只能感激所讨论的代码从未投入生产。做一次并且它看起来并没有什么害处,但是在整个地方做到这一点并且那种不安的感觉会安顿下来并且只会产生挫败感,直到你终于意识到为什么它是错的(按照上面的考虑)。如果您有点好奇,我会为表示几乎总是包裹单个基元的实体键的类型执行此操作。再一次,它似乎是一个明智的想法,它可能看起来像你,但我坚信它现在不是现在,即使我以前不会听到它。也许它是你需要在它最终沉入之前燃烧的事情之一。