c#中的前缀和后缀操作符重载

本文关键字:后缀 操作符 重载 前缀 | 更新日期: 2023-09-27 18:04:36

下面的代码有一个运行时问题,即由赋值后缀/前缀增量语句产生的意外引用,如下面的代码所示。也有人可以建议我用一种方法来对待对象作为值类型在c#中建议下面如果有的话?

我相信这段代码有很好的文档,注释阐明了每个重要的状态。关于代码的澄清或手头的问题,请随时提出任何问题。

提前感谢。

class Test {
    public int x;
    public Test(int x) { this.x=x; }    
    public Test() { x=0; }
    static public Test operator++(Test obj) {
        return new Test(obj.x+1);
    }   
}
 // In implementing module
 // Prefix/Postfix operator test for inbuilt (scalar) datatype 'int'
 int x=2;
 int y=++x; // 'y' and 'x' now both have value '3'
 Console.WriteLine(x++); // Displays '3'
 Console.WriteLine(++x); // Displays '5'
 Console.WriteLine(ReferenceEquals(x,y)); // Displays 'False'

 // Prefix/Postfix operator test of class type 'Test'
 Test obj=new Test();
 obj.x=1;
 Console.WriteLine(obj++); // Must have displayed '1', displays the object type (Test.Test)
 Console.WriteLine(++obj); // Must have displayed '3', again displays the object type (Test.Test)
 Console.WriteLine(obj.x); // Displays '3' (as expected)
 Test obj2=++obj; // Must have the value '4' and must NOT be the reference of obj
 // Alternative solution to the above statement can be : 'Test obj2=new Test(++obj);' but isn't there a way to create a new value type in C# by the above statement ??!! (In C++, it can be acheived by overloading the '=' operator but C# doesn't allow it)
 Console.WriteLine(obj2.x); // Displays '4' (as expected)
 Console.WriteLine(ReferenceEquals(obj,obj2)); // Must display 'False' but displays 'True' showing that 'obj2' is the reference of 'obj'

c#中的前缀和后缀操作符重载

基本上,您误解了这一行的工作原理:

Test obj2 = ++obj;

如果你把你的操作符当作一个方法来使用,那就像是在说:

obj = Test.operator++(obj);
obj2 = obj;

所以,是的,你最终得到objobj2是相同的参考。++obj的结果是obj 后应用++运算符的值,但++运算符也影响obj的值。

如果使用

Test obj2 = obj++;

那就等于:

Test tmp = obj;
obj = Test.operator++(obj);
obj2 = tmp;

此时,obj2的值为原对象,obj的值为新创建的对象,且x的值更高。

关于Console.WriteLine结果的其余问题实际上是因为您没有覆盖ToString()

您正在尝试调整声明为class的类型以表现为struct。这对我来说没有任何意义。如果您将class Test更改为struct Test,删除无参数构造函数并覆盖.ToString方法,则所有问题都解决了。

首先,每次递增(Post或Pre)时都创建了一个新的Test实例。所以当你输入这行:

Test obj2 = ++obj;

就好像你在写:

obj = new Test(obj.x + 1);
Test obj2 = obj;
第二,对于打印问题,只需重写ToString:
public override string ToString()
{
    return x.ToString();
}

如果您阅读了您提供的指向已删除答案的链接,则:

Test obj2 = ++obj;

被翻译成

temp = operator++(obj);
obj = temp;
obj2 = temp;

这意味着它们有相同的引用