IT story

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

hot-time 2020. 8. 6. 07:54
반응형

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의 의미에 대한 블로그를 작성했습니다 . 에릭 Lippert의 당 "나는 또한 VB / VBScript와 JScript의 널 (null)의 의미에 대해 쓴 여기여기 ."

NULL 값이 가능한 환경에서는 제외 된 중간의 법칙 (즉, A 또는 ~ A가 율 법적으로 참임)을 더 이상 신뢰할 수 없다는 것을 인식하는 것이 중요합니다.

최신 정보:

A bool와는 반대로 bool?TRUE 및 FALSE 값만 사용할 수 있습니다. 그러나 NULL의 언어 구현은 NULL이 표현식을 통해 전파되는 방식을 결정해야합니다. VB에서 표현식 5=null5<>nullBOTH는 false를 리턴합니다. C 상기 비교 식 #에서, 5==null그리고 5!=null단지 - [PG 업데이트 2014년 3월 2일] 이 거짓을 반환. 그러나 널을 지원하는 모든 환경에서는 프로그래머가 해당 언어에서 사용하는 진리표와 널 전파를 알아야합니다.


대신에를 x <> y반환 하기 때문 Nothing입니다 true. 정의되지 않았기 때문에 단순히 정의 x되지 않았습니다. (SQL 널과 유사).

참고 : VB.NET Nothing<> C # null.

값이있는 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 널 입력 가능 값 유형 ... 널 입력 가능 값 유형은 널 입력 가능하지 않은 버전의 유형 및 널 값과 동일한 값을 포함 할 수 있습니다. 따라서 널 입력 가능 값 유형의 경우, 유형의 변수에 Nothing을 지정하면 변수의 값이 값 유형의 0이 아닌 널값으로 설정됩니다.

예를 들면 다음과 같습니다.

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 #으로 변환했습니다).

씨#:

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로 변환되지 않은 undefined는 false입니다.

Nothing compared to whatever is always Nothing, not false in Visual Basic (it is the same as in SQL).


The problem that's observed here is a special case of a more general problem, which is that the number of different definitions of equality that may be useful in at least some circumstances exceeds the number of commonly-available means to express them. This problem is in some cases made worse by an unfortunate belief that it is confusing to have different means of testing equality yield different results, and such confusion might be avoided by having the different forms of equality yield the same results whenever possible.

In reality, the fundamental cause of confusion is a misguided belief that the different forms of equality and inequality testing should be expected to yield the same result, notwithstanding the fact that different semantics are useful in different circumstances. For example, from an arithmetic standpoint, it's useful to be able to have Decimal which differ only in the number of trailing zeroes compare as equal. Likewise for double values like positive zero and negative zero. On the other hand, from a caching or interning standpoint, such semantics can be deadly. Suppose, for example, one had a Dictionary<Decimal, String> such that myDict[someDecimal] should equal someDecimal.ToString(). Such an object would seem reasonable if one had many Decimal values that one wanted to convert to string and expected there to be many duplicates. Unfortunately, if used such caching to convert 12.3 m and 12.40 m, followed by 12.30 m and 12.4 m, the latter values would yield "12.3", and "12.40" instead of "12.30" and "12.4".

Returning to the matter at hand, there is more than one sensible way of comparing nullable objects for equality. C# takes the standpoint that its == operator should mirror the behavior of Equals. VB.NET takes the standpoint that its behavior should mirror that of some other languages, since anyone who wants the Equals behavior could use Equals. In some sense, the right solution would be to have a three-way "if" construct, and require that if the conditional expression returns a three-valued result, code must specify what should happen in the null case. Since that is not an option with languages as they are, the next best alternative is to simply learn how different languages work and recognize that they are not the same.

Incidentally, Visual Basic's "Is" operator, which is lacking in C, can be used to test for whether a nullable object is, in fact, null. While one might reasonably question whether an if test should accept a Boolean?, having the normal comparison operators return Boolean? rather than Boolean when invoked on nullable types is a useful feature. Incidentally, in VB.NET, if one attempts to use the equality operator rather than Is, one will get a warning that the result of the comparison will always be Nothing, and one should use Is if one wants to test if something is null.


May be this post well help you:

If I remember correctly, 'Nothing' in VB means "the default value". For a value type, that's the default value, for a reference type, that would be null. Thus, assigning nothing to a struct, is no problem at all.


This is a definite weirdness of VB.

In VB, if you want to compare two nullable types, you should use Nullable.Equals().

In your example, it should be:

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

Your VB code is simply incorrect - if you change the "x <> y" to "x = y" you will still have "false" as the result. The most common way of expression this for nullable instances is "Not x.Equals(y)", and this will yield the same behavior as "x != y" in C#.

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

반응형