2014-07-21 8 views
1

이상한 상황이 발생했습니다. 호출 된 하위가 전달 된 param을 새 값으로 설정 했더라도 폐기 된 객체가 여전히 호출 하위에서 액세스하려고하기 때문에 아래 코드는 실패합니다. upcasting가 관련된 경우VB.NET Upcasted ByRef는 ByVal처럼 동작합니다.

Sub Foo(ByRef astream as MemoryStream) 
    'do stuff 
    astream.Dispose() 
    astream = New MemoryStream() 
End Sub 

Sub Other() 
    Dim memstream as New MemoryStream() 
    Foo(memstream) 
    memstream.Position = 0' <- This works now! 
End Sub 

그래서, 왜 첫 번째는 작동하지 않으며, 두 번째 작품 :

Sub Foo(ByRef astream as Stream) 
    'do stuff 
    astream.Dispose() 
    astream = New MemoryStream() 
End Sub 

Sub Other() 
    Dim memstream as New MemoryStream() 
    Foo(CType(memstream, Stream)) 
    memstream.Position = 0' <- FAILS with Object Disposed! 
End Sub 

그러나 이것은 성공?

EDIT : VS 2013 용 June Roslyn CTP를 사용 중입니다 (버그가있는 경우).

감사합니다.

+0

+1 VS 2010을 사용하고 있는데 동작이 동일합니다. –

+0

@TimSchmelter이 점을 명확히 해 주셔서 감사합니다. 나는 그것이 디자인에 의한 것이라고 생각한다. 하지만 왜? –

답변

2
Foo(CType(memstream, Stream)) 

CType() 식은 임시 변수를 생성합니다. 그것이 업데이트 된 것입니다. 즉, 컴파일러는 다음과 같은 코드를 생성

당신의 memstream 변수가 업데이트되지 않습니다 분명히
Dim $Temp = CType(memstream, Stream) 
    Foo($Temp) 

. 다음과 같이 대신 명명 된 변수가 필요합니다.

Dim temp = CType(memstream, Stream) 
    Foo(temp) 
    memstream = temp 

또는 CType()은 필요하지 않으므로 사용하지 마십시오. 하위 대신 함수를 사용하여 이런 종류의 손실을 피할 수 있습니다.

Function Foo(ByVal astream as Stream) As MemoryStream 
    ''do stuff 
    astream.Dispose() 
    Return New MemoryStream() 
    End Function 

이 코드는 상당히 이상합니다.

마지막으로 컴파일러에서 진단을 내릴 수 있습니다. 프로젝트 + 속성, 컴파일 탭, 경고 구성 섹션. 없음에서 경고로 "암시 적 변환"을 변경하십시오. 그러나 시끄러운 경고가되는 경향이 있으며 일반적인 VB.NET 코드에는 많은 암시 적 변환이 있습니다.

+0

대단히 고마워요! 그것은 그것을 설명한다! 내 실제 코드는 여기에 넣은 것보다 더 복잡하고 이미 다른 것을 반환하는 함수이므로 함수 제안을 사용할 수 없습니다. 따라서 스트림을 반환 할 수 없습니다. 나는 당신이 제안한 것처럼 새로운 명명 된 변수를 선언하는 것으로 계속 고집 할 것입니다. –

+0

오, 제쳐두고 ... DirectCast가 대신 사용되면 다르게 동작합니까? –

+0

아니요, 아직 표현식입니다. 당신은 캐스팅의 필요성에 대해 계속 파고 들며, 실제로 함수를 사용해야한다고 강력하게 제안합니다. 스 니펫에 쓰여 있듯이 전달하는 인수는 오직 Stream 또는 MemoryStream 일 수 있습니다. 다른 것은 당신에게 짖을 것입니다. –