关于c#:如何添加或减去同一类/类型的两个实例

How to add or subtract two instances of the same class/type

我有一个表示数字类型的类型。在本例中,我使用的是兆瓦,所以我创建了一个名为兆瓦的类型。我希望能够像使用int、double或任何类型的c数字类型那样使用这些兆瓦。这有可能吗?如果是,我该怎么做?

例子:

1
2
3
public class Megawatt{
    public double Value { get; set; }
}

我希望能够做到:

1
2
3
var startOfDay = new Megawatts{value=100};
var endOfDay = new Megawatts{value=65};
Megawatt result = startOfDay - endOfDay;

这在datetime中是可能的…您可以从另一个日期时间中减去一个日期时间,得到一个时间跨度。我希望做些类似的事情。


除了到目前为止发布的很好的答案之外:您应该使您的类型成为不可变的结构,而不是可变的值类型。这正是为不可变值类型设计的作业类型。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
struct Megawatt
{
    private double Value { get; private set; }
    public Megawatt(double value) : this()
    {
        this.Value = value;
    }
    public static Megawatt operator +(Megawatt x, Megawatt y)
    {
        return new Megawatt(x.Value + y.Value);
    }
    public static Megawatt operator -(Megawatt x, Megawatt y)
    {
        return new Megawatt(x.Value - y.Value);
    }
    // unary minus
    public static Megawatt operator -(Megawatt x)
    {
        return new Megawatt(-x.Value);
    }
    public static Megawatt operator *(Megawatt x, double y)
    {
        return new Megawatt(x.Value * y);
    }
    public static Megawatt operator *(double x, Megawatt y)
    {
        return new Megawatt(x * y.Value);
    }
}

等等。请注意,您可以将两个兆瓦相加,但不能将两个兆瓦相乘;您只能将两个兆瓦相乘。

你也可以添加更多的单位负载类型。例如,您可以创建一个"兆瓦"和"小时"类型,然后说"兆瓦乘以小时"就是"兆瓦"。你也可以说有另一种焦耳,有一个隐式的转换,从兆瓦时到焦耳。

有许多编程语言支持这些类型的操作,它们的详细程度比C要低。如果你做了很多这样的事情,你可能会研究F。


您应该编写自己的运算符重载:

样品:

1
2
3
4
   public static Megawatt operator +(Megawatt c1, Megawatt c2)
   {
      return new Megawatt(c1.value+ c2.value);
   }


这称为运算符重载。我建议你阅读这篇文章:

http://msdn.microsoft.com/en-us/library/aa288467(v=vs.71).aspx

这是一个关于过程的教程。基本上,您可以更改这些类型的-操作符的含义。

例如(从链接中被盗)

1
2
3
4
public static Megawatt operator -(Megawatt c1, Megawatt c2)
{
  // do whatever you want here
}

这样你的负号就可以减去兆瓦。

您可以对任何类型或类型组合执行此操作。如果你愿意的话,你甚至还可以返回第三种类型。许多语言都支持这个概念,并且非常有用。


扩展答案:在这种情况下,运算符重载是可以肯定的。重载操作符是C中的一个很好的选项,它允许使用操作符代替类中的方法。

当重载诸如+这样的运算符时,相应的复合赋值运算符也会重载,例如+=

正如您在使用它们时想象的那样,操作符重载必须是static,并使用关键字operator,如@royinamir的答案中所示。

为了扩展答案,除了数学运算符之外,以下二进制比较运算符只能成对重载:

  • ==!=
  • ><
  • >=<=
  • 就代码设计建议而言,正如@royinamir所说,操作符重载应该存在于它们重载的类中。


    创建自己的类型是一个好主意;它可以防止火星着陆器的问题,你增加公斤和磅。但是,我建议将它们设置为structs,而不是类,因为这将使它们不可变,并消除初始化空值的可能性。另外,将value设为私有,这样您就可以执行以下操作:

    1
    2
    3
    var startOfDay = new Megawatts(100);
    var endOfDay = new Megawatts(65);
    Megawatt result = startOfDay - endOfDay;

    您还应该考虑实现IComparable<>IEquatable<>、转换运算符等等。这将允许您对Megawatt的集合进行比较和构造。

    做所有这些都是一项很大的工作;请参考C规范形式。