运营商超载

时间:2011-02-28 15:31:12

标签: c# operator-overloading

学习C#我读过有关运算符重载的内容。不幸的是,我使用的这本书不太实用而不是理论,所以我想确保我做得好。 基本上重载运算符也允许我使用我的类型进行操作。就像我有类Enemy,我可以做Enemy + Enemy = SuperEnemy(Enemy的例子,例如属性的总和) 是吗?

7 个答案:

答案 0 :(得分:2)

从概念的角度来看,是的;重载运算符允许您为运算符实现某些逻辑行为,因此可以以更自然的方式操作对象。举个例如,Money类:

public class Money
{
   public decimal Amount {get;set;}
   public string Unit {get;set;}
}

金钱通常被视为一个数字,因此能够加上和减去金钱来获得金额和差异会很好;然而,描述这笔钱的货币单位(美元,美国国防部,欧洲联盟,JYN)对它们的加入方式产生了很大的影响;添加100JPY + 100USD!= 200USD或200JPY。因此,您可能会使运营商超负荷以确保货币单位相似,或将其转换为另一个(100JPY~ = 1USD):

//in the above Money class
public static operator + (Money a, Money b)
{
    if(a.Unit != b.Unit) throw new InvalidOperationException("Cannot perform arithmetic on Money of two different types.")
    //or, create some helper that will convert the second term
    //CurrencyConverter.Convert(b.Amount, b.Unit, a.Unit);
    return new Money{Amount = a.Amount + b.Amount, Unit = a.Unit};
}

答案 1 :(得分:1)

是的,你可以这样做。我建议你只做非常非常。通过这种方式很容易得到难以理解的代码

有用的完成地点的例子是

DateTime operator +(DateTime dateTime, TimeSpan timeSpan)

因此您可以向TimeSpan添加DateTime以获取另一个DateTime

答案 2 :(得分:0)

一个很好的例子是例如为复数创建一个类,它们有operator +, - ,* etc,但行为比普通数字差。

以下是关于此的文章:http://msdn.microsoft.com/en-us/library/aa288467(v=vs.71).aspx

使用它们的另一个好地方是创建不可变类。

class SomeCoordinate{
  public int X {get;private set;}
  public int X {get;private set;}

  public SomeCoordinate(int X, int Y){
    this.X = X;
    this.Y = Y;
  }

  public static SomeCoordinate operator + (SomeCoordinate left, SomeCoordinate right) {
    // instead of changing the class, create a new one
    return new SomeCoordinate(left.X + right.X, left.Y + right.Y);
  }
}

} GJ

答案 3 :(得分:0)

只要你有代码来处理总和,你就可以做到。 但是,使用属性总和获取SuperEnemy对象需要使用代码来生成这些总和。

仅仅编写object + object = ...

就无法工作

看看这个: Operator Overloading

答案 4 :(得分:0)

虽然在C#中可以进行操作符重载,但您应该避免使用它!它只在非常狭窄的领域才有意义,比如你是否实现了自己的数字类(比如一个复数类)。在这种情况下,您可能会发现它很有用。但你应该问问自己,你多久经常创造这样的课程......实际上从来没有!更可能的示例是业务应用程序中的Money类或Date类。但即使在这里,我也会争辩说,如果添加两个实例的逻辑超过1-2行代码,那么沿着运算符重载的路径走错是错误的。特别是日期类很棘手并且具有与它们相关的各种业务需求 - 并且应该通过使用方法在代码中明确这些要求,而不是将它们隐藏在运算符重载下。

但请注意,有些运营商的负载比其他运营商差。许多人感到迫切需要重载==(意为Equals())。这绝对是可怕的,因为您在阅读代码时遇到了困难。特别是当说人们忘记过载时,例如。 !=

其他人认为可以重载+,但对于更大的对象,它可能并不完全清楚1)这意味着什么,2)它严重模糊了代码。话虽如此,我可能能够与超载+的人一起生活,而我却无法接受任何超载的人==

答案 5 :(得分:0)

他说的话。

在所涉及的各种类型的代码中完全理解时,强制执行只有每个操作符重载的规则。也就是说,将Type1和Type2一起添加在逻辑上是合理的,并且这种添加会导致Type3有意义。

你上面的例子没有遵守这个规则:它并不是说2个敌人组成了一个超级敌人。就个人而言,如果我需要这种逻辑,我会有一个静态方法来创建一个SuperEnemy,如: -

class SuperEnemy
{
  public static SuperEnemy FromEnemies(Enemy a, Enemy b)
  {
  }
}

您可能适当地使用运算符重载的更好的示例是颜色。你可以一起添加两种颜色并获得第三种颜色,两种颜色的混合颜色。所以: -

public static Color operator +(Color a, Color b)

将是一个明智的超载实施。

在一个现实世界的例子中:我有一个代表二维坐标的类,另一个代表一个二维矢量(即翻译)。

坐标+坐标=没有意义 - 不要重载

坐标+矢量=坐标

Vector + Vector =表示两个向量组合的新向量

我希望有帮助

答案 6 :(得分:0)

SuperEnemy = Enemy + Enemy

是的,如果您创建的超级敌人属于同一敌人类型,您可以像这样使用运算符重载。但是,如果您通过组合其他Type对象使用运算符重载来创建不同的类型,我认为它将违反单一责任原则。我们来看一个例子。

public class Type2 {}

public class Type1
{
    public static Type2 operator +(Type1 c1, Type1 c2)
    {
        return new Type2();
    }
}

Type1类中已经重载了'+'运算符以获取Type2类。通过运算符重载,我们使Type1类创建Type2以及Type1职责作为类。当我们创建Type2更改的方式时,Type1类实现也将更改。所以我认为,使用运算符重载来创建不同的对象将违反单一责任原则。

如果你使用运算符重载来组合两个Money类对象来创建另一个Money,那么这是有意义的。

您可以参考文章Operator overloading in C# with Money class example

相关问题