예상치 못한 복싱 및 참조 비교와 관련하여 VB.NET에서 비헤이비어가 발생했습니다. 설명하기 위해 모든 유형의 변수를 원자 적으로 업데이트하려고하는 간단한 프로그램을 작성했습니다.개체 권투의 차이점/C#과 VB.Net 간의 참조를 비교하는 것
using System;
public static class Program
{
private static object o3;
public static void Main()
{
Console.WriteLine("Hello World");
Test<DateTimeOffset?> value = new Test<DateTimeOffset?>();
Console.WriteLine(value.Value == null);
DateTimeOffset dt1 = new DateTimeOffset(2017, 1, 1, 1, 1, 1, TimeSpan.Zero);
DateTimeOffset dt2 = new DateTimeOffset(2017, 1, 2, 1, 1, 1, TimeSpan.Zero);
Console.WriteLine(value.TrySetValue(null, dt1));
Console.WriteLine(value.Value == dt1);
// this should fail
Console.WriteLine(value.TrySetValue(null, dt2));
Console.WriteLine(value.Value == dt1);
// this should succeed
Console.WriteLine(value.TrySetValue(dt1, dt2));
}
}
public class Test<T>
{
public T Value {
get { return (T)System.Threading.Volatile.Read(ref _value); }
}
private object _value;
public bool TrySetValue(T oldValue, T newValue)
{
object curValObj = System.Threading.Volatile.Read(ref _value);
if (!object.Equals((T)curValObj, oldValue))
return false;
object newValObj = (object)newValue;
return object.ReferenceEquals(System.Threading.Interlocked.CompareExchange(ref _value, newValObj, curValObj), curValObj);
}
}
이 프로그램의 출력은 다음과 같습니다 : 여기
는 C#에서 프로그램 ( https://dotnetfiddle.net/VsMBrg)입니다Hello World
True
True
True
False
True
True
이 예상 모든 것이 잘 작동하는 것 같다 같습니다. 여기
Imports System
Public Module Module1
private o3 as object
Public Sub Main()
Console.WriteLine("Hello World")
Dim value As New Test(Of DateTimeOffset?)
Console.WriteLine(value.Value is nothing)
Dim dt1 As New DateTimeOffset(2017, 1, 1, 1, 1, 1, TimeSpan.Zero)
Dim dt2 As New DateTimeOffset(2017, 1, 2, 1, 1, 1, TimeSpan.Zero)
Console.WriteLine(value.TrySetValue(Nothing, dt1))
Console.WriteLine(value.Value = dt1)
' This should fail
Console.WriteLine(value.TrySetValue(Nothing, dt2))
Console.WriteLine(value.Value = dt1)
' This should succeed
Console.WriteLine(value.TrySetValue(dt1, dt2))
End Sub
End Module
public class Test(Of T)
Public readonly Property Value As T
Get
Return CType(Threading.Volatile.Read(_value), T)
End Get
End Property
Private _value As Object
Public Function TrySetValue(oldValue As T, newValue As T) As Boolean
Dim curValObj As Object = Threading.Volatile.Read(_value)
If Not Object.Equals(CType(curValObj, T), oldValue) Then Return False
Dim newValObj = CObj(newValue)
Return Object.ReferenceEquals(Threading.Interlocked.CompareExchange(_value, newValObj, curValObj), curValObj)
End Function
end class
출력은 다음과 같습니다 : 여기
Hello World
True
True
True
False
True
False
마지막 문 세트가 작동하지 않았 음을 의미 거짓 다음은 VB.NET (https://dotnetfiddle.net/lasxT2)에서 같은 프로그램입니다. 내가 여기 뭔가 잘못하고있는 중이거나 VB.NET에서 문제가 있습니까?
(참고 :이 예제가 스레딩의 영향을받지 않습니다 그래서 스레드가 없습니다, 휘발성이 읽기/쓰기 무시) : 나는 T는 정수로 변경하면 다음 모든 확인을 작동합니다
편집을
(dotnetfiddle.net/X6uLZs). 나는 사용자 정의 클래스에 T를 변경하는 경우 또한 그것은 또한 OK 작동합니다
dotnetfiddle.net/LnOOme
IL을 보면 C# 명령어는 'unbox.any'이며 여기서 vb 명령어는'Conversions '입니다.ToGenericParameter'. 그래서 VB는 구조체의 복사본을 반환하지만 C#은 동일한 구조체를 참조하고 있음을 의미합니까? –
Crowcoder
@Crowcoder -이 작은 코드 샘플에서 만들어진 예상치 못한 복사본의 전단 번호로 어떤 VB 코드가 전혀 작동하는지 질문하게되었습니다 :-( –
CLR 소스 코드에서 : "기술적으로 우리는 boxed DateTimes와 Decimals를 복사하지 않고 반환 할 수 있습니다 여기에서 VB는 고객에게 큰 변화가 될 것이라는 것을 깨달았으므로 복사하십시오. " –