2

以下代码存在运行时问题,即通过分配后缀/前缀增量语句产生的意外引用,如下面的代码所示。如果有的话,任何人都可以向我建议一种将对象视为 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'
4

3 回答 3

4

基本上,您误解了这条线的工作原理:

Test obj2 = ++obj;

如果您考虑将运算符用作一种方法,这就像说:

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

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

如果你使用

Test obj2 = obj++;

那么这相当于:

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

此时,值obj2将引用原始对象,而值obj将引用新创建的具有更高x值的对象。

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

于 2016-08-30T10:14:23.570 回答
1

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

Test obj2 = ++obj;

被翻译成

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

这意味着它们具有相同的参考。

于 2016-08-30T10:13:17.127 回答
1

您正在尝试调整声明为class表现为struct. 这对我来说没有任何意义。如果改成class Teststruct 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();
}
于 2016-08-30T10:14:25.700 回答