【问题标题】:Overloading the + operator to add two arrays重载 + 运算符以添加两个数组
【发布时间】:2010-12-13 19:55:22
【问题描述】:

这段 C# 代码有什么问题?我试图重载 + 运算符来添加两个数组,但收到如下错误消息:

二元运算符的参数之一必须是包含类型。

class Program
{
  public static void Main(string[] args)
  {
      const int n = 5;

      int[] a = new int[n] { 1, 2, 3, 4, 5 };
      int[] b = new int[n] { 5, 4, 3, 2, 1 };
      int[] c = new int[n];

      // c = Add(a, b);
      c = a + b;

      for (int i = 0; i < c.Length; i++)
      {
        Console.Write("{0} ", c[i]);
      }

      Console.WriteLine();
  }

  public static int[] operator+(int[] x, int[] y)
  // public static int[] Add(int[] x, int[] y)
  {
      int[] z = new int[x.Length];

      for (int i = 0; i < x.Length; i++)
      {
        z[i] = x[i] + y[i];
      }

      return (z);
  }
}

【问题讨论】:

  • 关于重载的 MSDN 教程页面有更多信息 - msdn.microsoft.com/en-us/library/aa288467%28VS.71%29.aspx
  • 这可能是你的答案:stackoverflow.com/questions/172658/…
  • 我们正在考虑将“扩展运算符”添加到假设的 C# 未来版本中,这将解决您的问题。民意调查:你们中的任何人都有这个功能的很棒的场景吗?我们可以获得的真实场景越多,某天就越有可能实现某个功能。按我的方式送他们;您可以使用我博客上的电子邮件链接。
  • 谢谢埃里克。这是否意味着我们还将获得“扩展一切”:)
  • 我们如何做到这一点,或者我应该放弃多态性直到我成为多神论者?

标签: c# operator-overloading


【解决方案1】:

运算符必须在“相关”类的主体中声明。例如:

public class Foo
{
    int X;

    // Legal
    public static int operator+(int x, Foo y);

    // This is not
    public static int operator+(int x, int y);
}

由于您无权访问数组的实现,最好的办法是将数组包装在您自己的实现中,这样您就可以提供额外的操作(这是使 operator+ 工作的唯一方法。

另一方面,您可以定义如下扩展方法:

public static class ArrayHelper
{
    public static int[] Add(this int[] x, int[] y) { ... }
}

这仍然会导致自然调用 (x.Add(y)),同时避免将数组包装在您自己的类中。

【讨论】:

    【解决方案2】:

    你可以这样使用:

    class Program {
      static void Main(string[] args) {
        const int n = 5;
    
        var a = new int[n] { 1, 2, 3, 4, 5 }.WithOperators();
        var b = new int[n] { 5, 4, 3, 2, 1 };
    
        int[] c = a + b;
    
        for (int i = 0; i < c.Length; i++) {
          Console.Write("{0} ", c[i]);
        }
    
        Console.WriteLine();
      }
    }
    
    public static class Int32ArrayExtensions {
      public static Int32ArrayWithOperators WithOperators(this int[] self) {
        return self;
      }
    }
    
    public class Int32ArrayWithOperators {
      int[] _array;
    
      public Int32ArrayWithOperators(int[] array) {
        if (array == null) throw new ArgumentNullException("array");
        _array = array; 
      }
    
      public static implicit operator Int32ArrayWithOperators(int[] array) {
        return new Int32ArrayWithOperators(array); 
      }
      public static implicit operator int[](Int32ArrayWithOperators wrapper) {
        return wrapper._array;
      }
    
      public static Int32ArrayWithOperators operator +(Int32ArrayWithOperators left, Int32ArrayWithOperators right) {
        var x = left._array;
        var y = right._array;
        return x.Zip(y, (a, b) => a + b).ToArray();
      }
    }
    

    基于我写的相关post

    【讨论】:

    • 我最初赞成这个,因为我的第一个阅读是这个它可以让编译器认为你在​​数组上定义了方法。但是,经过反思,我发现它只是允许您隐藏这样一个事实,即您所做的是用一层间接来包装数组。包装数组是获取 + 运算符的一种简单而明显的解决方案,但它引入了我不想要的其他开销。
    • 是的,包装数组是获得所需内容的一种简单方法,但这还不是全部。隐式转换运算符使您可以更轻松地从包装器移动到数组,反之亦然。最后,这只是一个关于如何伪造扩展运算符的想法,但绝对不完美。
    【解决方案3】:

    它声明操作符的参数之一需要与操作符函数所属的类型相同。因此,如果操作符函数是 MyClass 的成员,则参数需要是 MyClass 类型。

    class MyClass
    {
     ...
    
    public static int[] operator+(MyClass x, int[] y)
      // public static int[] Add(int[] x, int[] y)
      {
          int[] z = new int[x.Length];
    
          for (int i = 0; i < x.Length; i++)
          {
            z[i] = x[i] + y[i];
          }
    
          return (z);
      }
    }
    

    【讨论】:

      【解决方案4】:

      当您想在 AA 和 BB 类型之间重载 le + 运算符时,您必须在 AA 或 BB 类中进行,而不是在名为 Program 的类中进行(就像您所做的那样)。

      很遗憾,您无法在 Array 类中编写代码

      你能做的就是

      • 创建您自己的实现 IList 的类
      • 并将 + 运算符放在该类上。

      如果你需要更详细的实现,尽管问我。

      【讨论】:

      • 太糟糕了,一个类无法以匹配数组下标行为的方式实现this[int](返回byref而不是一个值)。
      【解决方案5】:

      您只能将运算符添加到您自己创建的类型。 int[] 是一种内置类型,您不能向其添加运算符。

      您可以创建自己的封装数组的类,并将运算符添加到其中。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-12-13
        • 1970-01-01
        • 1970-01-01
        • 2021-08-29
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-08-31
        相关资源
        最近更新 更多