2016-08-30 4 views
2

다음 코드는 코드에서 볼 수 있듯이 접미사/접두사 증가 문의 할당으로 인해 예기치 않은 참조가 발생하는 런타임 문제가 있습니다. 또한 누구나 C#에서 값 유형으로 객체를 처리하는 방법을 제안 해 주시겠습니까?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' 
+2

네 음, ToString()을 오버 라이딩하지 않았습니다. 그 시점에서 이의 제기의 절반이 사라집니다. * single * 문제를 시연하는 [mcve]를 쓰면 정말 도움이 될 것입니다. –

+0

@ user3185569 : 나는 그 의견을 삭제했다. 'obj'와'obj2'에 대한 부분이 괜찮을 것 같아서요 ... 여기에 많은 문제가 얽혀있는 것은 도움이되지 않습니다. –

+0

사실, 'Test obj2 = ++ obj' 부분의 문제점을 봅니다. 그것에 대한 답을 추가 할 것입니다. –

답변

1

class으로 선언 된 유형을 struct으로 작동하도록 조정하려고합니다. 이것은 나를 위해 어떤 이해가되지 않습니다. class Teststruct Test으로 변경하면 매개 변수없는 생성자를 제거하고 .ToString 메서드를 재정 의하여 모든 문제가 해결됩니다.

먼저, 증가 (게시 또는 사전) 할 때마다 Test의 새 인스턴스를 만듭니다.그래서 당신이 줄을 명중 할 때 :

Test obj2 = ++obj; 

것은 당신이 쓰고있어 마치를 :

obj = new Test(obj.x + 1); 
Test obj2 = obj; 

두 번째 및 인쇄 문제에 관해서는, 단지 toString를 오버라이드 (override) 해, :

public override string ToString() 
{ 
    return x.ToString(); 
} 
+0

그럼 어떻게하면 같은 참조를 가질 수 없습니까? 답변 감사합니다. – hecate

+0

@hecate 그렇다면 참조로 취급되기를 원하지 않는다면 클래스로'Test'를 가질 이유가 없습니다. 그러면 그것을 '구조체'로 변환하십시오. 그렇게하면 Copy by Value 의미론을 가지게되며이 문제는 사라집니다. – user3185569

+0

감사합니다. 'Test'클래스를 구조로 변환했습니다. Thanks again again :) – hecate

1

당신이 link 당신이 다음, 삭제 된 답변을 제공 읽으면 :

Test obj2 = ++obj; 

들은이 같은 기준을 의미합니다

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

로 변환됩니다.

+0

그러면 어떻게 내가 같은 참조를 갖지 못하게 할 수 있을까요? 답변 감사합니다. – hecate

+0

++ 연산자 만 사용하려는 경우에는 사용할 수 없습니다. '증가 된 '버전에 대해서 하나의 인스턴스 만 생성됩니다. – Maarten

4

기본적으로, 당신이 오해 한이 라인의 작동 방법 :

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

그래서 그래, 당신은 결국 : 당신이 방법으로 당신의 연산자를 사용하여 생각하는 경우

Test obj2 = ++obj; 

, 그 말처럼 objobj2은 동일한 참조 번호입니다. ++obj의 결과는 ++ 연산자를 적용한 연산자 이후에 obj값이지만 ++ 연산자는 obj 값에도 영향을줍니다. 당신이

Test obj2 = obj++; 

를 사용하는 경우

다음 그와 동등의 : 그 시점에서

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

, obj2의 값은 원래 객체를 참조하고, obj의 vlaue은 참조합니다 새롭게 생성 된 객체는 더 높은 x 값을가집니다.

Console.WriteLine의 결과를 둘러싼 질문의 나머지 부분은 실제로 ToString()을 재정의하지 않았기 때문에 발생합니다.

+0

그러면 어떻게 내가 같은 참조를 갖지 못하게 할 수 있습니까? 답변 감사합니다. – hecate

+0

@hecate : 할 수 없습니다. 'Test obj2 = ++ obj; '는 마지막 부분이'obj2 = obj;'라는 것을 의미합니다. 다른 견해를 제시 하시려면 어떻게 생각하십니까? 만약'Test'가 불변이라면, 그것은 중요하지 않습니다. (다른 곳에서 언급했듯이'Test'를 구조체로 만들 수는 있지만 아무 곳이나 참조 할 수는 없습니다 ...) –

관련 문제