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;

そうです、あなたは同じ参照になりますobjobj2の結果は、演算子を適用した++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メソッドをオーバーライドすると、すべての問題がなくなります。

まず、インクリメントするたびに Test の新しいインスタンスを作成しています (Post または Pre)。したがって、この行にヒットすると:

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 に答える