code

VB.NET 및 C#의 값에 대해 null을 확인하는 데 차이가 있는 이유는 무엇입니까?

starcafe 2023. 5. 18. 21:12
반응형

VB.NET 및 C#의 값에 대해 null을 확인하는 데 차이가 있는 이유는 무엇입니까?

VB.NET에서는 다음과 같은 현상이 발생합니다.

Dim x As System.Nullable(Of Decimal) = Nothing
Dim y As System.Nullable(Of Decimal) = Nothing

y = 5
If x <> y Then
    Console.WriteLine("true")
Else
    Console.WriteLine("false") '' <-- I got this. Why?
End If

그러나 C#에서는 다음과 같은 일이 발생합니다.

decimal? x = default(decimal?);
decimal? y = default(decimal?);

y = 5;
if (x != y)
{
    Debug.WriteLine("true"); // <-- I got this -- I'm with you, C# :)
}
else
{
    Debug.WriteLine("false");
}

왜 차이가 있는거죠?

VB.NET과 C#.NET은 서로 다른 언어로, 사용에 대해 서로 다른 가정을 한 다른 팀에 의해 구축되었습니다. 이 경우 NULL 비교의 의미입니다.

개인적으로 선호하는 것은 VB.NET 의미론이며, 이는 본질적으로 NULL에 "아직 모릅니다"라는 의미를 부여합니다.그러면 5를 "아직 모릅니다"와 비교하면 자연스럽게 "아직 모릅니다" 즉, NULL입니다.이렇게 하면 SQL 데이터베이스에서 NULL의 동작을 미러링할 수 있는 추가적인 이점이 있습니다.이것은 또한 여기서 설명하는 것처럼 3값 논리에 대한 (C#의) 더 표준적인 해석입니다.

C# 팀은 NULL이 무엇을 의미하는지에 대해 서로 다른 가정을 했고, 이로 인해 사용자가 보여주는 동작 차이가 발생했습니다.Eric Lippert는 C#에서 NULL의 의미에 대해 블로그를 썼습니다.Per Eric Lippert: "저는 또한 VB/VBScript와 JScript의 null의 의미에 대해 여기와 여기에 썼습니다."

NULL 값이 가능한 모든 환경에서 제외된 중간의 법칙(즉, A 또는 ~A가 엄밀하게 사실임)을 더 이상 신뢰할 수 없음을 인식하는 것이 중요합니다.

업데이트:

A bool((으)로 되는 bool? 및 값만 할 수 는 TRUE 및 FALSE 값만 사용할 수 있습니다.그러나 NULL의 언어 구현은 NULL이 식을 통해 전파되는 방식을 결정해야 합니다. VB 서표식5=null그리고.5<>null둘 다 거짓을 반환합니다.에서, 한 표현식 중 C# 서비교가능식중한에식 ▁in중▁of한능가ions5==null그리고.5!=null번째 [업데이트 2014-03-02 - PG]만 false를 반환합니다.그러나 null을 지원하는 모든 환경에서는 해당 언어에 사용되는 true 테이블과 null-propagation을 아는 것이 프로그래머의 의무입니다.

갱신하다

의미론에 대한 Eric Lippert의 블로그 기사(아래 댓글에 언급됨)는 다음 사이트에 있습니다.

ㅠㅠx <> y아온다를 합니다.Nothingtrue다음과 같이 정의되지 않았습니다.x정지않다니습았 ( null과함)(SQL null은 " "입니다.")

파일: VB.NETNothing<> C#null.

a의 .Nullable(Of Decimal)가치가 있는 경우에만.

따라서 위의 VB.NET은 다음과 유사합니다(정확하지 않은 것으로 보입니다).

If x.HasValue AndAlso y.HasValue AndAlso x <> y Then
    Console.WriteLine("true")
Else
    Console.WriteLine("false")  
End If

VB.NET 언어 사양:

7.1.1 Nullable유형...null 가능한 값 유형에는 null이 아닌 버전의 유형과 동일한 값과 null 값이 포함될 수 있습니다.따라서 null 가능한 값 유형의 경우 Nothing을 유형의 변수에 할당하면 변수 값이 값 유형의 0이 아닌 null 값으로 설정됩니다.

예:

Dim x As Integer = Nothing
Dim y As Integer? = Nothing

Console.WriteLine(x) ' Prints zero '
Console.WriteLine(y) ' Prints nothing (because the value of y is the null value) '

생성된 CIL을 확인합니다(둘 다 C#으로 변환했습니다).

C#:

private static void Main(string[] args)
{
    decimal? x = null;
    decimal? y = null;
    y = 5M;
    decimal? CS$0$0000 = x;
    decimal? CS$0$0001 = y;
    if ((CS$0$0000.GetValueOrDefault() != CS$0$0001.GetValueOrDefault()) ||
        (CS$0$0000.HasValue != CS$0$0001.HasValue))
    {
        Console.WriteLine("true");
    }
    else
    {
        Console.WriteLine("false");
    }
}

비주얼 베이직:

[STAThread]
public static void Main()
{
    decimal? x = null;
    decimal? y = null;
    y = 5M;
    bool? VB$LW$t_struct$S3 = new bool?(decimal.Compare(x.GetValueOrDefault(), y.GetValueOrDefault()) != 0);
    bool? VB$LW$t_struct$S1 = (x.HasValue & y.HasValue) ? VB$LW$t_struct$S3 : null;
    if (VB$LW$t_struct$S1.GetValueOrDefault())
    {
        Console.WriteLine("true");
    }
    else
    {
        Console.WriteLine("false");
    }
}

Visual Basic의 비교 결과 Nullable<bool>(bool, false 또는 true!가 아님)이 반환됩니다.그리고 bool로 변환된 정의되지 않은 것은 거짓입니다.

Nothing NothingVisual Basic에서는 false가 아닙니다(SQL과 동일합니다).

여기서 관찰되는 문제는 보다 일반적인 문제의 특별한 경우인데, 적어도 어떤 상황에서 유용할 수 있는 평등의 다양한 정의의 수가 그것들을 표현하기 위해 일반적으로 사용 가능한 수단의 수를 초과한다는 것입니다.이 문제는 어떤 경우에는 평등을 테스트하는 다른 수단이 다른 결과를 산출하는 것이 혼란스럽다는 불행한 믿음으로 더 악화되고, 가능할 때마다 다른 형태의 평등이 동일한 결과를 산출하도록 함으로써 그러한 혼란을 피할 수 있습니다.

사실, 혼란의 근본적인 원인은 다른 상황에서 다른 의미론이 유용함에도 불구하고 다른 형태의 평등 및 불평등 테스트가 동일한 결과를 산출할 것으로 기대해야 한다는 잘못된 믿음입니다.예를 들어, 산술적인 관점에서 볼 때, 그것은 다음과 같은 것을 가질 수 있는 것이 유용합니다.Decimal동일하게 비교되는 후행 0의 수만 다릅니다.에도 마찬가지로double양의 0과 음의 0과 같은 값.반면에, 캐싱이나 인터닝의 관점에서 볼 때, 그러한 의미론은 치명적일 수 있습니다.예를 들어, 어떤 사람이 가지고 있다고 가정해 보겠습니다.Dictionary<Decimal, String> 식으로myDict[someDecimal]같야합 다니아와 .someDecimal.ToString()만약 한 사람이 많은 것을 가지고 있다면 그러한 물건은 합리적으로 보일 것입니다.Decimal문자열로 변환하고 중복이 많을 것으로 예상한 값입니다.불행히도, 이러한 캐싱을 사용하여 12.3m와 12.40m를 변환한 후 12.30m와 12.4m를 변환하면, 후자의 값은 "12.30"과 "12.4" 대신 "12.3"과 "12.40"을 산출합니다.

당면한 문제로 돌아가서, 평등을 위해 무효가 되는 물체를 비교하는 합리적인 방법이 한 가지 이상 있습니다.C#은 다음과 같은 입장을 취합니다.==연산자는 다음의 동작을 반영해야 합니다.EqualsVB.NET은 그것의 행동이 다른 언어들의 행동을 반영해야 한다는 입장을 취합니다, 왜냐하면 누구나 그것을 원하는 사람이기 때문입니다.Equals행동은 사용할 수 있습니다.Equals어떤 의미에서, 올바른 해결책은 3방향 "if" 구조를 갖는 것이고, 만약 조건식이 3값 결과를 반환한다면, 코드는 다음에서 무엇이 발생해야 하는지를 명시해야 합니다.null사례. 언어를 그대로 사용하는 옵션이 아니기 때문에, 다음으로 좋은 대안은 단순히 다른 언어들이 어떻게 작동하는지 배우고 그것들이 같지 않다는 것을 인식하는 것입니다.

덧붙여서, C에 없는 Visual Basic의 "Is" 연산자는 null 가능한 객체가 실제로 null인지 테스트하는 데 사용될 수 있습니다.어떤 사람은 합리적인 질문을 할 수 있지만,if테스트는 a를 받아들여야 합니다.Boolean?정상 비교 연산자가 복귀하도록 하기Boolean?Boolean한 유형에서 때기능입니다. 이 기능은 다음과 같습니다.수적으로가 VB입니다.NET에서, 만약 누군가가 다음과 같은 연산자를 사용하려고 한다면.Is비교의 결과는 항상 다음과 같을 것이라는 경고를 받을 것입니다.Nothing 그고사야합니다해용리합다▁use니▁and를 사용해야 합니다.Is어떤 것이 무효인지 시험하고 싶은 경우.

게시물이 도움이 될 수 있습니다.

내 기억이 맞다면, VB의 '아무것도'는 "기본값"을 의미합니다.값 유형의 경우 기본값이고 참조 유형의 경우 null입니다.따라서 구조체에 아무것도 할당하지 않는 것은 전혀 문제가 되지 않습니다.

이것은 확실히 VB의 이상한 점입니다.

두 가지 하려면 VB 에서두가 null 능유형비을교다면합사니다음용을 사용해야 합니다.Nullable.Equals().

예를 들어, 다음과 같이 해야 합니다.

Dim x As System.Nullable(Of Decimal) = Nothing
Dim y As System.Nullable(Of Decimal) = Nothing

y = 5
If Not Nullable.Equals(x, y) Then
    Console.WriteLine("true")
Else
    Console.WriteLine("false")
End If

VB 코드가 잘못되었을 뿐입니다. "x <> y"를 "x = y"로 변경해도 결과적으로 "false"가 표시됩니다.null 가능한 인스턴스에 대한 가장 일반적인 표현 방법은 "x가 아닙니다.(y)"와 같으며, 이는 C#의 "x!= y"와 동일한 동작을 생성합니다.

언급URL : https://stackoverflow.com/questions/15524045/why-is-there-a-difference-in-checking-null-against-a-value-in-vb-net-and-c

반응형