C #에 두 개의 개체가 있으며 부울인지 또는 다른 유형인지 알 수 없습니다. 그러나 C #을 비교하려고하면 올바른 대답을하지 못합니다. VB.NET과 동일한 코드를 사용해 보았습니다.
해결책이 있다면 누구 든지이 문제를 해결하는 방법을 말해 줄 수 있습니까?
씨#:
object a = true;
object b = true;
object c = false;
if (a == b) c = true;
MessageBox.Show(c.ToString()); //Outputs False !!
VB.NET :
Dim a As Object = True
Dim b As Object = True
Dim c As Object = False
If (a = b) Then c = True
MessageBox.Show(c.ToString()) '// Outputs True
답변
C #에서 ==
연산자 (참조 유형 표현식에 적용되는 경우)는 오버로드 되지 않는 한 참조 동등성 검사를 수행합니다 . 복싱 변환의 결과 인 두 개의 참조를 비교하고 있으므로 고유 한 참조입니다.
편집 :을 오버로드하는 유형을 사용 ==
하면 다른 동작을 얻을 수 있지만 표현식 의 컴파일 타임 유형을 기반으로합니다 . 예를 들어 다음을 string
제공합니다 ==(string, string
.
string x = new string("foo".ToCharArray());
string y = new string("foo".ToCharArray());
Console.WriteLine(x == y); // True
Console.WriteLine((object) x == (object) y); // False
여기서 첫 번째 비교는 오버로드 된 연산자를 사용하지만 두 번째 비교는 “기본”참조 비교를 사용합니다.
VB에서 =
연산자는 훨씬 더 많은 작업 을 수행합니다. 텍스트를 비교하는 방법에 영향을 줄 수 object.Equals(x, y)
있기 때문에 를 사용하는 것과 동등하지 않습니다 Option Compare
.
기본적으로 운영자는 같은 방식으로 작동하지 않으며되지 않은 목적으로 같은 방식으로 작동 할 수 있습니다.
답변
C # 측면을 설명하는 Jon의 답변 외에도 VB의 기능은 다음과 같습니다.
VB with Option Strict On
에서을 통한 비교는 =
항상 값 평등을 테스트하고 참조 평등을 테스트하지 않습니다. 실제로을 정의하지 않기 Option Strict On
때문에 전환하면 코드가 컴파일 System.Object
되지 않습니다 Operator=
. 항상 이 옵션을 설정 해야 합니다. 비너스 플라이 트랩보다 버그를 더 효과적으로 잡을 수 있습니다 (특정 경우이 느슨한 동작이 실제로 올바른 일을하지만). 1
사실,과 Option Strict On
에서 C #을 : VB C #을보다 더 엄격한 동작 a == b
중 하나 를 호출을 트리거 SomeType.operator==(a, b)
이, (호출하는 것과 같습니다 발동 참조 평등 비교를 존재하지 않는 경우, 또는 object.ReferenceEquals(a, b)
).
반면에 VB에서는 비교가 a = b
항상 항등 연산자를 호출합니다. 2 참조 동등 비교를 사용하려면을 a Is b
다시 사용해야합니다 (다시 한번 동일 Object.ReferenceEquals(a, b)
).
1) 그 이유를 사용하여 좋은 표시이다 Option Strict Off
나쁜 생각한다 : 나는 몇 년 전까지 .NET의 공식 출시 이전부터 거의 10 중고 VB.NET을했습니다, 그리고 나는 전혀 생각도 없어 무엇을 a = b
함께 수행을 Option Strict Off
. 그것은 어떤 종류의 평등 비교를 수행하지만, 정확히 무슨 일이 일어나고, 왜, 전혀 모른다. C #의 dynamic
기능 보다 더 복잡 합니다 (잘 문서화 된 API에 의존하기 때문에). MSDN의 내용은 다음과 같습니다.
때문에
Option Strict On
제공하는 강력한 입력을 , 데이터 손실을 의도하지 않은 형식 변환, 런타임에 바인딩 것을 허용하지를 방지하고 성능을 향상, 그것의 사용을 적극 권장합니다.
2) Jon은 동등성 비교가 이전 버전과의 호환성 때문에 더 많은 일을하는 곳에서 문자열 예외를 언급했습니다.
답변
객체 인스턴스는 연산자 “==”와 비교되지 않습니다. “같음”방법을 사용해야합니다. “==”연산자를 사용하면 객체가 아닌 참조를 비교합니다.
이 시도:
public class MyObject
{
public MyObject(String v)
{
Value = v;
}
public String Value { get; set; }
}
MyObject a = new MyObject("a");
MyObject b = new MyObject("a");
if(a==b){
Debug.WriteLine("a reference is equal to b reference");
}else{
Debug.WriteLine("a reference is not equal to b reference");
}
if (a.Equals(b)) {
Debug.WriteLine("a object is equal to b object");
} else {
Debug.WriteLine("a object is not equal to b object");
}
결과 :
a reference is not equal to b reference
a object is not equal to b object
이제 이것을 시도하십시오 :
public class MyObject
{
public MyObject(String v)
{
Value = v;
}
public String Value { get; set; }
public bool Equals(MyObject o)
{
return (Value.CompareTo(o.Value)==0);
}
}
MyObject a = new MyObject("a");
MyObject b = new MyObject("a");
if(a==b){
Debug.WriteLine("a reference is equal to b reference");
}else{
Debug.WriteLine("a reference is not equal to b reference");
}
if (a.Equals(b)) {
Debug.WriteLine("a object is equal to b object");
} else {
Debug.WriteLine("a object is not equal to b object");
}
결과 :
a reference is not equal to b reference
a object is equal to b object
답변
문제는 C #의 == 연산자 가 두 매개 변수 의 컴파일 시간 유형 을 기반으로 정적 메서드 (기술적으로는 아니지만 그렇게 할 수 있음)에 대한 호출이라는 것입니다. 해당 객체의 실제 런타임 유형은 중요하지 않습니다.
해당 컴파일 시간 유형을 기반으로 컴파일러는 operator ==
사용할 구현을 결정 합니다. 기본 object
구현을 사용하거나 언어에서 제공하는 숫자 과부하 중 하나를 사용하거나 사용자 정의 구현 일 수 있습니다.
VB는 컴파일 타임에 구현을 결정하지 않는다는 점에서 VB와 다릅니다. 런타임까지 대기 ==
하고 사용해야 하는 연산자의 구현을 판별하기 위해 제공되는 두 개의 매개 변수를 검사합니다 .
코드에 부울 값이 포함되어 있지만 유형이 변수에 있습니다 object
. 때문에 변수가 형이고 object
, C # 컴파일러는 사용 object
구현 ==
비교 참조 하지 객체 인스턴스. 부울 값은 상자이므로 값이 같더라도 동일한 참조를 갖지 않습니다.
VB 코드는 변수의 유형을 신경 쓰지 않습니다. 런타임까지 기다렸다가 두 변수를 확인하고 변수가 실제로 부울 유형 인 것을 확인 하여 부울 ==
연산자 구현을 사용합니다 . 이 구현은 참조가 아닌 부울 값을 비교합니다 (부울은 해당 연산자를 호출하기 전에 상자가 풀리므로 참조 비교는 더 이상 의미가 없습니다). 부울 값이 같으므로 true를 리턴합니다.
답변
