2013-06-30 1 views
2

이 질문은 실제 필요 이상으로 호기심에서 벗어났습니다.ByRef 매개 변수에 전달 된 매개 변수가 지정된 "기타"변수와 저장 위치를 ​​공유하는 경우 런타임에 테스트

ByRef (즉 C#의 ref 또는 out) 매개 변수에 전달 된 인수가 "기타"변수와 동일한 저장 위치를 ​​갖는지 테스트 할 수있는 방법이 있습니까? 두 개의 다른 참조 변수가 동일한 객체에 대한 두 개의 서로 다른 참조 일 수 있기 때문에 객체가 동일한 지 여부를 테스트하는 것은 아닙니다.

나는 무슨 뜻인지 설명하기 위해 몇 가지 예를 생각해 냈습니다. 고려 :

public static void SillySwap(ref int a, ref int b) 
{ 
    // first put sum of original numbers into slot a, 
    // then use that to get out the original numbers swapped 
    a = a + b; 
    b = a - b; 
    a = a - b; 
} 

(우리가 일반적으로 대신 세 번째 임시 변수를 사용합니다,하지만 내 질문을 설명하기 위해이 같은 해.) 잘 작동 SillySwap 당신이 변수에 올 경우, 동일하거나 다른 하나 수치. 그렇게 같이 호출한다면 :

int shared = 42; 
SillySwap(ref shared, ref shared); 

shared을 전멸 할 것이다. ab이 저장 위치와 동일하면 SillySwap의 본문 내부에서 테스트 할 수있는 방법이 있습니까?

여기 ("클래스 변수") 필드와 변형 예이다 :

여기
protected static int field; 
public static void SillySwap2(ref int arg) 
{ 
    arg = arg + field; 
    field = arg - field; 
    arg = arg - field; 
} 

우리가 전달 된 arg 실제로 변수 field했다 있는지 확인하고 싶습니다.

최종 예를 들어, 다음 사항을 고려하십시오

static bool SillyTryGetStrings(out string first, out string second) 
{ 
    // the order of assignment may matter here! 
    second = "world"; 
    first = "Hello"; 

    return true; 
} 

가 이상한 사람이 firstsecond에 대해 동일한 변수에 전달하자. 우리는 그 방법 안에서 그 것을 확인할 수 있습니까?

답변

3

한 가지 방법은 변수에 대한 포인터를 안전하지 않은 코드를 사용하고 비교하는 것입니다 :

public unsafe bool AreRefsEqual(ref int a, ref int b) 
{ 
    fixed (int* aptr = &a) 
    fixed (int* bptr = &b) 
    { 
     return aptr == bptr; 
    }   
} 

[TestMethod] 
public void ShouldRefsEqualWork() 
{ 
    int a = 1, b = 1; 
    Assert.IsTrue(AreRefsEqual(ref a, ref a)); 
    Assert.IsFalse(AreRefsEqual(ref a, ref b));   
} 
+0

매우 흥미 롭군요. 'unsafe' 메소드는'int'뿐만 아니라 모든 값 타입과 참조 타입을 다루기 위해 일반화 될 수 있습니까? –

+0

제약 조건에 상관없이 제네릭 형식의 주소를 사용할 수 없기 때문에 C#으로 처리 할 수 ​​있다고 생각하지 않습니다 (몇 가지 유형의 주소 만 사용할 수 있음). 나는 그것이 C++/CLI에서 가능할 것이라고 생각한다. – ghord

+0

그래서 당신의 솔루션은 부분적인 것입니다. 그것은 몇 가지 한계가 있습니다. (1) 값 유형 (참조 유형의 인스턴스 필드가없는 값 유형에만 해당)에서만 작동합니다. (2) unassigned 변수의 단항'&'연산자를 사용하여 주소를 가져 오는 것이 합법적입니다. 그래서''int int i' 매개 변수가 있고 처음에 주소를 확인하려면, 코드 "인라인"을 사용하지만, 확실히 할당되지 않았기 때문에'AreRefsEqual' 메서드에'i'를 전달할 수 있다고 생각하지 않습니다. –

관련 문제