【问题标题】:C# overload operator gives different resultsC# 重载运算符给出不同的结果
【发布时间】:2016-02-04 22:45:13
【问题描述】:

为我的自定义向量和矩阵类之间的数学运算编写代码我遇到了一个奇怪的(至少对我而言)问题。

类型之间的重载运算符在不同的地方给出不同的结果。我发现操作的结果对如何在“运算符+(...)”中创建新实例很敏感。

我创建了显示差异的简单代码(见下文)。 两个班级正在做同样的事情,并且预期的结果相同,但实际上并不相同。 Type2 的重载运算符和函数“test”修改了变量。 我在 MSDN 中没有发现任何关于此的警告。此行为不直接由语法标记(例如,由“ref”关键字)。

谁能推荐一个关于这个问题的链接? 是预测的行为还是 C# 语法中的错误?

using System;

namespace test_operator_overload
{
    class Program
    {
        static void Main()
        {
            Type1 A1 = new Type1(1);
            Console.WriteLine(A1);          // 1 - OK
            Console.WriteLine(A1 + A1);     // 2 - OK
            Console.WriteLine(A1);          // 1 - OK

            Console.WriteLine();

            Type2 B1 = new Type2(1);
            Console.WriteLine(B1);          // 1 - OK
            Console.WriteLine(B1 + B1);     // 2 - OK
            Console.WriteLine(B1);          // 2 - Not OK

            Console.WriteLine();

            Type2 C1 = new Type2(1);
            Console.WriteLine(C1);          // 1 - OK
            Console.WriteLine(test(C1));    // 2 - OK
            Console.WriteLine(C1);          // 2 - Not OK
        }

        static Type2 test(Type2 a)
        {
            a.x += 1;
            return a;
        }
    }



    class Type1
    {
        public double x;

        public Type1(double x)
        {
            this.x = x;
        }

        public static Type1 operator +(Type1 a, Type1 b)
        {
            return new Type1(a.x + b.x);
        }

        public override string ToString() { return GetType().Name + " (" + x + ")"; }
    }


    class Type2
    {
        public double x;

        public Type2(double x)
        {
            this.x = x;
        }

        public static Type2 operator +(Type2 a, Type2 b)
        {
            a.x += b.x;
            return a;
        }

        public override string ToString() { return GetType().Name + " (" + x + ")"; }
    }
}

【问题讨论】:

  • 寻求调试帮助的问题(“为什么这段代码不起作用?”)必须包括所需的行为、特定的问题或错误以及在问题本身中重现它所需的最短代码。没有明确问题陈述的问题对其他读者没有用处。请参阅:如何创建最小、完整和可验证的示例。
  • 改变操作符中的参数势必会引起混淆。没有人预料到运营商会产生这些副作用。
  • 您的clsB 运算符没有创建新实例。它们在表达式求值期间改变您的操作数的属性。因此,B2 的属性,在其表达式中使用了两次,对于两个不同的操作具有不同的值。
  • @mybirthname 旁注:对于 cmets 使用 [ MCVE ](无空格)来获取文本链接。还给你额外的字符:)
  • 关于主题:请查看Why mutable structs are evil - 正如@mikez 所说,这是一个非常糟糕的主意,与float 和其他.numeric 类型上的常规运算符完全不同。

标签: c# operator-overloading reference-type


【解决方案1】:

Type2 的 + 运算符不正确,您不应修改运算符中的输入。

运算符通过组合输入并返回新结果来对输入进行操作。

【讨论】:

  • 是的,我已经将 struct 应用于我所有使用重载运算符的类。现在它快了大约 30%。但是我在示例中解释的问题仍然不清楚。正如 MSDN 中提到的:link“......当控制权传回调用过程时,更改的值将不会被保留。”在我的示例中,当我使用重载运算符或调用函数“test”时,参数值在控件传递回调用过程后更改。所以。怎么了?
  • 嗯,它完全按照你的要求做。添加输入,然后将输入值之一设置为等于结果.. 运算符与函数没有什么不同,因为它们通过引用获取输入,并且可以修改它们的值。
  • 文档@Dennis 指的是关于按值传递与按引用传递的讨论,而不是“传递 a 引用”,因此虽然他引用的文档在技术上是正确的,但它与他的问题无关。
猜你喜欢
  • 1970-01-01
  • 2014-03-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-01
相关资源
最近更新 更多