18

我有一个代表数字类型的类型。在本例中,我使用的是兆瓦,因此我创建了一种称为兆瓦的类型。我希望能够像使用 Int、Double 或任何类型的 c# 数字类型一样使用这些兆瓦。这可能吗?如果是这样,我该怎么做?

例子:

public class Megawatt{
    public double Value { get; set; }
}

我希望能够做到这一点:

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

这可以通过 DateTime... 您可以从另一个 DateTime 中减去一个 DateTime 并获得一个 TimeSpan。我希望做类似的事情。

4

5 回答 5

35

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

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

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

您还可以添加更多包含单元的类型。例如,您可以创建一个 MegawattHour 类型和一个 Hour 类型,然后说 Megawatt 乘以 Hour 等于 MegawattHour。您也可以说存在另一种焦耳类型,并且存在从兆瓦时到焦耳的隐式转换。

有许多编程语言支持这些类型的操作,而且比 C# 更简洁;如果你做了很多这类事情,你可能会研究 F#。

于 2012-04-30T21:57:18.897 回答
11

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

样本 :

   public static Megawatt operator +(Megawatt c1, Megawatt c2) 
   {
      return new Megawatt(c1.value+ c2.value);
   }
于 2012-04-30T21:45:54.117 回答
2

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

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

这是一个关于该过程的教程。基本上,您更改了-这些类型的运算符的含义。

作为示例(从链接中窃取)

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

这样你的减号现在可以减去兆瓦

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

于 2012-04-30T21:45:48.113 回答
1

扩展答案:在这种情况下,运算符重载肯定是要走的路。重载运算符是 C# 中的一个很好的选择,它允许使用运算符代替类中的方法。

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

正如您对它们的使用所想象的那样,运算符重载必须是static并使用operator@RoyiNamir 的答案中的关键字。

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

  1. ==!=
  2. ><
  3. >=<=

至于代码设计建议,就像@RoyiNamir 所说,运算符重载应该存在于它们重载运算符的类中。

于 2012-04-30T22:09:21.847 回答
0

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

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

您还应该考虑实现IComparable<>, IEquatable<>, 转换运算符等。这将允许您对 s 进行比较并构建其集合Megawatt

做所有这些工作量很大。请参阅C# 规范形式

于 2012-04-30T22:20:26.580 回答