C #에서 ==와! =를 모두 정의해야하는 이유는 무엇입니까?


346

C # 컴파일러는 사용자 정의 유형이 operator를 정의 할 때마다 정의 ==해야합니다 !=( 여기 참조 ).

왜?

디자이너가 왜 필요하다고 생각했는지 그리고 왜 다른 사람 만 존재할 때 컴파일러가 운영자 중 하나를 위해 합리적인 구현을 기본으로 할 수 없는지 알고 싶습니다. 예를 들어 Lua를 사용하면 항등 연산자 만 정의하고 다른 연산자는 무료로 얻을 수 있습니다. C #은 == 또는 == 및! =를 모두 정의한 다음 누락 된! = 연산자를로 자동 컴파일하여 동일한 작업을 수행 할 수 !(left == right)있습니다.

IEEE-754 NaN과 같이 일부 엔터티가 같거나 같지 않은 이상한 경우가 있지만 예외가 아닌 예외처럼 보입니다. 따라서 C # 컴파일러 디자이너가 예외를 규칙으로 만든 이유는 설명하지 않습니다.

평등 연산자가 정의 된 솜씨가 좋지 않은 경우를 보았습니다. 불평등 연산자는 모든 비교가 역전되고 모든 &&가 || (당신은 요점을 얻습니다 ... 기본적으로! (a == b) De Morgan의 규칙을 통해 확장되었습니다). Lua의 경우와 마찬가지로 컴파일러가 의도적으로 설계를 통해 제거 할 수있는 것은 좋지 않습니다.

참고 : 연산자 <> <=> =도 마찬가지입니다. 부 자연스러운 방법으로 정의 해야하는 경우를 상상할 수 없습니다. Lua를 사용하면 <와 <= 만 정의하고 전자의 부정을 통해 자연스럽게> =와>를 정의 할 수 있습니다. C #이 왜 똑같이하지 않습니까 (적어도 '기본적으로')?

편집하다

프로그래머가 원하는대로 평등과 불평등에 대한 검사를 구현할 수있는 정당한 이유가있는 것 같습니다. 대답 중 일부는 그것이 좋은 경우를 지적합니다.

그러나 내 질문의 핵심은 일반적 으로 논리적으로 필요 하지 않은 C #에서 이것이 강제적으로 필요한 이유는 무엇 입니까?

그것은 .NET 인터페이스 등에 선택을 설계하는 현저한 대조도 Object.Equals, IEquatable.Equals IEqualityComparer.Equalsa의 부족 어디 NotEquals프레임 워크 간주하는 대응 쇼 !Equals()불평등 한 물체를하고있어. 또한, 클래스와 같은 클래스 Dictionary와 메소드 .Contains()는 위에서 언급 한 인터페이스에만 의존하며 정의 된 경우에도 연산자를 직접 사용하지 않습니다. ReSharper에서 평등 멤버를 생성 할 때 사실, 그것은 모두 정의 ==!=측면에서 Equals()그렇다하더라도 사용자 선택한다면 모두에서 운영자를 생성 할 경우에만합니다. 프레임 워크에서는 객체 동등성을 이해하기 위해 동등 연산자가 필요하지 않습니다.

기본적으로 .NET 프레임 워크는 이러한 연산자를 신경 쓰지 않고 몇 가지 Equals방법 만 신경 씁니다 . == 및! = 연산자를 사용자가 함께 정의해야한다는 결정은 순수한 언어 설계와 관련이 있으며 .NET에 관한 한 객체 의미는 아닙니다.


24
훌륭한 질문은 +1입니다. 전혀 이유가없는 것 같습니다 ... 물론 컴파일러는 달리 언급하지 않는 한 a! = b가! (a == b)로 변환 될 수 있다고 가정 할 수 있습니다. 그들이 왜 그렇게하기로 결정했는지 궁금합니다.
Patrick87

16
이것은 내가 투표하고 좋아하는 질문을 본 것 중 가장 빠릅니다.
Christopher Currens

26
@Eric Lippert도 좋은 답변을 제공 할 수 있다고 확신합니다.
Yuck

17
"과학자는 정답을주는 사람이 아니라, 올바른 질문을하는 사람이다." 이것이 SE에서 질문이 장려되는 이유입니다. 그리고 작동합니다!
Adriano Carneiro

4
파이썬에 대한 동일한 질문 : stackoverflow.com/questions/4969629/…
Josh Lee

답변:


161

언어 디자이너를 위해 말할 수는 없지만 내가 추론 할 수있는 것은 의도적이고 적절한 디자인 결정 인 것 같습니다.

이 기본 F # 코드를 살펴보면이를 작업 라이브러리로 컴파일 할 수 있습니다. 이것은 F #에 대한 법적 코드이며 불평등이 아닌 항등 연산자에만 과부하를줍니다.

module Module1

type Foo() =
    let mutable myInternalValue = 0
    member this.Prop
        with get () = myInternalValue
        and set (value) = myInternalValue <- value

    static member op_Equality (left : Foo, right : Foo) = left.Prop = right.Prop
    //static member op_Inequality (left : Foo, right : Foo) = left.Prop <> right.Prop

이것은 정확히 어떻게 보이는지 수행합니다. 동등 비교기 ==만 작성 하고 클래스의 내부 값이 같은지 확인합니다.

C #에서는 이와 같은 클래스를 만들 수 없지만 .NET 용으로 컴파일 된 클래스 사용할 있습니다. 오버로드 된 연산자를 사용할 것이므로 == 런타임은 !=무엇을 사용 합니까?

C # EMCA 표준에는 등식을 평가할 때 사용할 연산자를 결정하는 방법을 설명하는 전체 규칙이 있습니다 (섹션 14.9). 지나치게 단순화되어 완벽하게 정확하지 않게하기 위해 비교중인 유형이 동일한 유형 이고 오버로드 된 동등 연산자가있는 경우 Object에서 상속 된 표준 참조 동등 연산자가 아닌 해당 오버로드를 사용합니다. 따라서 연산자 중 하나만 존재하는 경우 기본 참조 동등 연산자를 사용하고 모든 객체에 대해 과부하가없는 것은 놀라운 일이 아닙니다. 1

이것이 사실이라는 것을 알면 실제 질문은 다음과 같습니다. 왜 이런 식으로 설계 되었는가? 그리고 왜 컴파일러가 스스로 알아 내지 못합니까? 많은 사람들이 이것이 디자인 결정이 아니라고 말하지만, 특히 모든 객체에 기본 항등 연산자가 있다는 사실과 관련하여 이것이 그렇게 생각되었다고 생각합니다.

그렇다면 컴파일러가 !=연산자를 자동으로 생성하지 않는 이유는 무엇입니까? Microsoft의 누군가가 이것을 확인하지 않으면 확실하지 않지만 사실에 대한 추론에서 결정할 수 있습니다.


예기치 않은 동작을 방지하려면

아마도 ==평등을 테스트하기 위해 값을 비교하고 싶습니다 . 그러나 그것이 왔을 때 !=참조가 같지 않으면 값이 같은지 전혀 신경 쓰지 않았습니다. 프로그램이 그 값을 동일하게 간주하기 때문에 참조가 일치하는 경우에만 관심이 있습니다. 결국 이것은 실제로 C #의 기본 동작으로 요약됩니다 (다른 언어로 작성된 일부 .net 라이브러리의 경우와 같이 두 연산자가 모두 오버로드되지 않은 경우). 컴파일러가 자동으로 코드를 추가했다면 더 이상 호환되는 코드를 출력하기 위해 컴파일러에 의존 할 수 없었습니다. 컴파일러는 특히 사용자가 작성한 코드가 C # 및 CLI의 표준 내에있는 경우 동작을 변경하는 숨겨진 코드를 작성해서는 안됩니다.

그것의 측면에서 강제 대신 기본 동작에 가고, 그것은 과부하, 난 단지 단단히 표준 (EMCA-334 17.9.2)에 있다고 말할 수있다 2 . 표준은 이유를 명시하지 않습니다. 나는 이것이 C #이 C ++에서 많은 행동을 빌리기 때문이라고 생각합니다. 이에 대한 자세한 내용은 아래를 참조하십시오.


!=과 를 재정의하면 ==부울을 반환 할 필요가 없습니다.

이것은 또 다른 이유입니다. C #에서이 함수는 다음과 같습니다.

public static int operator ==(MyClass a, MyClass b) { return 0; }

이것만큼 유효합니다 :

public static bool operator ==(MyClass a, MyClass b) { return true; }

bool 이외의 것을 반환하면 컴파일러 자동으로 반대 유형을 유추 할 수 없습니다 . 또한 연산자 부울을 반환 하는 경우에는 특정 사례에만 존재하는 코드를 생성하거나 위에서 언급했듯이 CLR의 기본 동작을 숨기는 코드를 생성하는 것이 의미가 없습니다.


C #은 C ++ 3 에서 많은 돈을 빌린다

C #이 소개되었을 때 MSDN 잡지에 C #에 관한 기사가 실 렸습니다.

많은 개발자들은 Visual Basic처럼 쉽게 작성하고 읽고 유지 관리 할 수있는 언어가 있었지만 여전히 C ++의 기능과 유연성을 제공하기를 원했습니다.

그렇습니다. C #의 디자인 목표는 C ++과 거의 동일한 양의 전력을 공급하는 것이 었으며, 엄격한 형식 안전성 및 가비지 수집과 같은 편의를 위해 약간만 희생했습니다. C #은 C ++ 이후에 강력하게 모델링되었습니다.

이 예제 프로그램 에서 보듯 C ++에서 항등 연산자는 bool을 반환하지 않아도 된다는 사실에 놀라지 않을 것입니다.

이제 C ++를 직접하지 않습니다 필요로 보완 연산자를 오버로드 할 수 있습니다. 예제 프로그램에서 코드를 컴파일 한 경우 오류없이 코드가 실행되는 것을 볼 수 있습니다. 그러나 라인을 추가하려고 시도한 경우 :

cout << (a != b);

당신은 얻을 것이다

컴파일러 오류 C2678 (MSVC) : 이진 '! =': 'Test'유형의 왼쪽 피연산자를 취하는 연산자를 찾을 수 없습니다 (또는 허용되는 변환이 없음)`.

C ++ 자체가 쌍으로 오버로드 할 필요가 없습니다 동안 그래서, 그것은 하지 않습니다 당신이 사용자 정의 클래스에 오버로드되지 않았 음을 동등 연산자를 사용 할 수 있습니다. 모든 개체에는 기본 개체가 있으므로 .NET에서 유효합니다. C ++은 그렇지 않습니다.


1. 부수적으로, C # 표준에서는 어느 한쪽에 과부하를 가하려는 경우 여전히 한 쌍의 연산자에 과부하가 걸리도록 요구합니다. 이것은 단순한 컴파일러가 아닌 표준 의 일부입니다 . 그러나 호출 할 연산자 결정에 관한 동일한 규칙은 동일한 요구 사항이없는 다른 언어로 작성된 .net 라이브러리에 액세스 할 때 적용됩니다.

2. EMCA-334 (pdf) ( http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-334.pdf )

3. 그리고 Java, 그러나 그것은 실제로 여기서 중요한 것은 아닙니다.


75
" 당신은 bool을 반환 할 필요가 없습니다 ".. 나는 그것이 바로 우리의 대답이라고 생각합니다. 잘 했어. ! (o1 == o2)가 잘 정의되어 있지 않으면 표준에 의존 할 것으로 기대할 수 없습니다.
Brian Gordon

10
논리적으로 논리 연산자에 대한 주제에서 문장에서 "C #을 사용하면 둘 중 하나만 무시할 수 없습니다"라는 문장에서 이중 음수를 사용했습니다. 실제로 논리적으로 "C #은 둘 중 하나만 무시할 수 있습니다"라는 의미입니다.
Dan Diplo

13
@ Dan Diplo, 괜찮습니다. 그렇게하지 않는 것이 금지되지 않는 것은 아닙니다.
Christopher Currens

6
사실이라면 # 2가 맞다고 생각합니다. 그러나 이제 질문은 왜 ==그렇지 bool않은가? 를 반환하면 int더 이상 조건문으로 사용할 수 없습니다. if(a == b)더 이상 컴파일되지 않습니다. 점은 무엇인가?
BlueRaja-대니 Pflughoeft

2
묵시적 변환을 가진 객체를 bool (오퍼레이터 true / false)로 반환 할 수는 있지만 여전히 유용한 곳을 찾지 못했습니다.
Stefan Dragnev

53

누군가가 3 값 논리 (즉 null) 를 구현 해야하는 경우에 적합합니다 . 예를 들어 ANSI 표준 SQL과 같은 경우에는 입력에 따라 연산자를 부정 할 수 없습니다.

다음과 같은 경우가있을 수 있습니다.

var a = SomeObject();

그리고 a == true되돌아 falsea == false도 돌아갑니다 false.


1
이후 나는 그 경우라고 말하고 싶지만 a당신이 3 상 열거가 아닌 실제와 비교해야 부울되지 않습니다 true또는 false.
Brian Gordon

18
그건 그렇고, 아무도 FileNotFound 농담을 참조한 것을 믿을 수 없습니다 .
Brian Gordon

28
경우 a == true이다 false나는 항상 기대 a != truetrue,에도 불구하고 a == falsefalse
Fede

20
@Fede는 머리에 못을 박았다. 이것은 실제로 질문과는 아무런 관련이 없습니다. 왜 누군가가 재정의 ==해야하는지 아닌 왜 재정의 해야하는지 설명 하고 있습니다.
BlueRaja-대니 Pflughoeft

6
@Yuck-그렇습니다. 좋은 기본 구현이 있습니다. 일반적인 경우입니다. 귀하의 예에서도 기본 구현은 !=정확합니다. 우리가 원 하고 거짓 이되는 매우 드문 경우에 (나는 이해가되는 단일 예제를 생각할 수 없다) , 그들은 여전히 ​​기본 구현을 무시하고 그들 자신을 제공 할 수있다. 일반적인 경우를 항상 기본값으로 설정하십시오! x == yx != y
BlueRaja-대니 Pflughoeft

25

C #이 많은 분야에서 C ++을 연기하는 것 외에, 내가 생각할 수있는 가장 좋은 설명은 경우에 따라 "평등"을 증명하는 것과 "평등하지 않음"을 증명 하는 약간 다른 접근법을 원할 수 있다는 것입니다.

예를 들어 문자열 비교를 사용 return하면 일치하지 않는 문자가 표시 될 때 동등성 및 루프 외부를 테스트 할 수 있습니다 . 그러나 더 복잡한 문제로 인해 그렇게 깨끗하지 않을 수 있습니다. 꽃 필터는 마음에 온다; 매우 요소가있는 경우 신속하게 말할 쉽게 하지 요소가 있다면 알려 세트에, 그러나 어려운 입니다 세트에. 동일한 return기술을 적용 할 수 있지만 코드가 예쁘지 않을 수 있습니다.


6
좋은 예입니다. 나는 당신이 이유에 있다고 생각합니다. 간단한은 !정보통 코더 최적화 할 수 있습니다 평등에 대한 하나의 정의로 당신을 잠급니다 모두 ==!=.
Yuck

13
따라서이 두 가지를 무시할 수있는 옵션 을 제공해야하는 이유를 설명 해야 합니다.
BlueRaja-대니 Pflughoeft

1
그 맥락에서 그들은 두 가지를 모두 최적화 할 필요가 없으며 , 두 가지 모두에 대한 명확한 정의제공하면 됩니다.
Jesper

22

.net 소스에서 == 및! =의 오버로드 구현을 보면 종종! = as! (left == right)를 구현하지 않습니다. 그들은 부정 논리로 그것을 완전히 구현합니다 (= =와 같은). 예를 들어 DateTime은 ==를 다음과 같이 구현합니다.

return d1.InternalTicks == d2.InternalTicks;

그리고! = as

return d1.InternalTicks != d2.InternalTicks;

당신 (또는 컴파일러가 암시 적으로 수행 한 경우)이라면! = as

return !(d1==d2);

그런 다음 클래스가 참조하는 것들에서 == 및! =의 내부 구현에 대해 가정합니다. 그러한 가정을 피하는 것은 그들의 결정 뒤에 철학이 될 수 있습니다.


17

하나를 재정의하면 둘 다 재정의 해야하는 이유와 관련하여 편집에 응답하려면 모두 상속됩니다.

==를 재정의하는 경우 일종의 의미 또는 구조적 동등성을 제공 할 가능성이 높습니다 (예를 들어, InternalTicks 속성이 다른 인스턴스를 통해도 동일한 경우 DateTimes는 동일 함). 모든 .NET 개체의 부모 인 개체입니다. == 연산자는 C #에서 기본 구현 Object.operator (==)가 참조 비교를 수행하는 메소드입니다. Object.operator (! =)는 다른 비교 방법이며 참조 비교도 수행합니다.

거의 모든 다른 방법을 재정의하는 경우, 하나의 방법을 재정의하면 반의어 적 방법에 대한 행동 변화가 발생한다고 가정하는 것은 비논리적입니다. Increment () 및 Decrement () 메서드를 사용하여 클래스를 만들고 자식 클래스에서 Increment ()를 재정의하는 경우 재정의 된 동작과 반대로 Decrement ()가 재정의 될 것으로 예상하십니까? 컴파일러는 모든 가능한 경우 연산자의 구현을 위해 역함수를 생성 할만큼 똑똑하게 만들 수 없습니다.

그러나 연산자는 메서드와 매우 유사하게 구현되지만 개념적으로 쌍으로 작동합니다. == 및! =, <및> 및 <= 및> =. 이 경우 소비자의 관점에서! =는 ==와 다르게 작동한다고 생각하는 것은 비논리적입니다. 따라서 컴파일러는 모든 경우에 a! = b ==! (a == b)라고 가정 할 수 없지만 일반적으로 ==와! =는 비슷한 방식으로 작동해야하므로 컴파일러는 쌍으로 구현해야하지만 실제로 그렇게합니다. 클래스의 경우 a! = b ==! (a == b) 인 경우! (==)를 사용하여! = 연산자를 구현하면됩니다. 그러나 해당 규칙이 객체의 모든 경우에 적용되지 않는 경우 (예 : 같거나 같지 않은 특정 값과의 비교가 유효하지 않은 경우 IDE보다 똑똑해야합니다.

실제 질문은 숫자 용어로! (a <b) == a> = b 및! (a> 인 경우 <및> 및 <= 및> =이 비교 연산자의 쌍인 이유입니다. b) == a <= b. 하나를 재정의하는 경우 네 가지를 모두 구현해야하며 a가 의미 적으로 (a <= b) == (a == b)이므로 == (및! =)도 재정의해야합니다. b와 같습니다.


14

! =가 아닌 사용자 정의 유형에 대해 ==를 오버로드하면 모든 것이 객체에서 파생되므로! = 객체의! = 객체에 의해 처리됩니다. 이는 CustomType! = CustomType과 크게 다릅니다.

또한 언어 작성자는 코더에게 최대한의 유연성을 제공하고 사용자가 수행하려는 작업에 대해 가정하지 않도록이 방법을 원했을 것입니다.


이 질문에 영감
Brian Gordon

2
유연성 이유는 예를 들어, 그들은 밖으로 떠나기로 결심하는 수많은 기능에 적용 할 수 blogs.msdn.com/b/ericlippert/archive/2011/06/23/... 그것은 그들의 선택을 설명하지 않습니다 .Thus 평등 연산자의 구현.
Stefan Dragnev

매우 흥미 롭습니다. 유용한 기능인 것 같습니다. 나는 그들이 왜 그 일을 그만 두 었는지 전혀 모른다.
Chris Mullins

11

이것이 내 마음에 먼저 오는 것입니다.

  • 불평등 테스트가 평등 테스트보다 훨씬 빠르면 어떻게해야 합니까?
  • 어떤 경우에 대해 와를 모두 반환하려면false==!= 어떻게해야합니까 (즉, 어떤 이유로 비교할 수없는 경우)

5
첫 번째 경우 불평등 테스트 측면에서 평등 테스트를 구현할 수 있습니다.
Stefan Dragnev

두 번째 경우는 같은 구조를 깰 것입니다 Dictionary그리고 List당신이 그들과 함께 사용자 정의 형식을 사용합니다.
Stefan Dragnev

2
@Stefan : Dictionary사용 GetHashCode하고 Equals,하지 연산자. List을 사용합니다 Equals.
Dan Abramov

6

글쎄, 그것은 아마도 디자인 선택 일뿐이지만, 당신이 말한 것처럼와 x!= y같을 필요는 없습니다 !(x == y). 기본 구현을 추가하지 않으면 특정 구현을 구현하는 것을 잊을 수 없습니다. 그리고 실제로 말한 것처럼 사소한 경우 다른 것을 사용하여 구현할 수 있습니다. 나는 이것이 어떻게 '가난한 실천'인지 알지 못한다.

C #과 Lua 사이에 다른 차이점이있을 수도 있습니다 ...


1
하나는 다른 하나의 측면에서 구현하는 것이 좋습니다. 방금 다른 방법으로 오류가 발생하는 것을 보았습니다.
Stefan Dragnev

3
이것이 C #의 문제가 아니라 프로그래머의 문제입니다. 이 권한을 구현하지 못한 프로그래머는 다른 영역에서도 실패합니다.
GolezTrol

@ GolezTrol : 루아 참조를 설명해 주시겠습니까? 나는 루아에 전혀 익숙하지 않지만 참조는 무언가를 암시하는 것 같습니다.
zw324

@Ziyao Wei : OP는 Lua가 C #과 다르게이 작업을 수행한다고 지적합니다 (Lua는 언급 된 연산자에 대한 기본 대응 항목을 추가합니다). 그런 비교를 간단하게하려고합니다. 전혀 차이가 없다면, 그들 중 적어도 하나는 존재할 권리가 없습니다. 루아도 모른다고 말해야합니다.
GolezTrol

6

질문의 핵심 단어는 " "와 " 필수 "입니다.

결과적으로 :

그들이 그렇게 설계 되었기 때문에 이런 식으로 대답하는 것은 사실입니다 ...하지만 질문의 "왜"부분에는 대답하지 않습니다.

이 두 가지를 독립적으로 재정의하는 것이 도움이 될 수 있다고 대답하는 것은 사실입니다 ...하지만 질문의 "필수"부분에는 대답하지 않습니다.

간단한 대답은 C # 두 가지를 모두 무시 해야하는 설득력있는 이유 가 없다는입니다 .

언어 만 오버라이드 (override) 할 수 있도록해야 ==하고, 당신의 기본 구현을 제공 !=!그. 재정의하고 싶을 때도 !=마찬가지입니다.

좋은 결정이 아니 었습니다. 인간은 언어를 디자인하고, 인간은 완벽하지 않으며, C #은 완벽하지 않습니다. 어깨를 으 and하고 QED


5

여기에 훌륭한 답변을 추가하십시오.

연산자 로 들어가서 대신 연산자 로 들어 가려고 할 때 디버거 에서 일어날 일을 고려하십시오 ! 혼란에 대해 이야기하십시오!!===

CLR은 많은 언어에서 작동해야하므로 하나 또는 다른 연산자를 자유롭게 제거 할 수 있습니다. 그러나 C 번호는 (CLR 기능을 노출하지 않는 예는 많이있다 ref(: 예 CLR 자체에없는 기능을 구현하는 예 예를 들어, 반환과 지역 주민을), 그리고 많은 using, lock, foreach, 등).


3

프로그래밍 언어는 매우 복잡한 논리 문의 구문 재 배열입니다. 이를 염두에두고 비평 등의 경우를 정의하지 않고 평등의 경우를 정의 할 수 있습니까? 내 대답은 아니오 야. 객체 a가 객체 b와 동일하기 위해서는 객체 a의 역수가 b와 같지 않아야합니다. 이것을 보여주는 또 다른 방법은

if a == b then !(a != b)

이것은 언어가 객체의 평등을 결정할 수있는 확실한 능력을 제공합니다. 예를 들어, NULL! = NULL 비교는 같지 않은 명령문을 구현하지 않는 동등 시스템의 정의에 렌치를 던질 수 있습니다.

이제! =의 아이디어와 관련하여 다음과 같이 단순히 대체 가능한 정의입니다.

if !(a==b) then a!=b

나는 그것에 대해 논쟁 할 수 없다. 그러나 C # 언어 사양 그룹은 프로그래머가 개체의 동등성과 비 균등성을 함께 명시 적으로 정의해야한다는 결정을 내 렸습니다.


Nullnull대한 유효한 입력 이기 때문에 문제 가 ==될 것입니다. 물론 매우 편리해서는 안됩니다. 개인적으로는 방대한 양의 모호하고 조잡한 프로그래밍이 가능하다고 생각합니다.
nicodemus13

2

요컨대 강제 일관성.

'=='와 '! ='는 정의하는 방법에 관계없이 "같음"과 "같지 않음"의 구두 정의로 정의 된대로 항상 반대입니다. 그중 하나만 정의하면 주어진 두 값에 대해 '=='와 '! ='둘 다 true이거나 둘 다 false 일 수있는 항등 연산자 불일치가 발생합니다. 하나를 정의하기로 결정할 때, "평등"의 정의가 무엇인지 명확하게 알 수 있도록 다른 하나도 적절하게 정의해야하기 때문에 두 가지를 모두 정의해야합니다. 컴파일러의 다른 솔루션은 '=='OR '! ='만 무시하고 다른 하나는 본질적으로 다른 하나를 무시하는 것으로 남겨 두는 것입니다. 분명히, C # 컴파일러의 경우에는 해당되지 않으며 확실합니다.

물어봐야 할 질문은 "왜 연산자를 재정의해야합니까?"입니다. 그것은 강력한 추론이 필요한 강력한 결정입니다. 개체의 경우 '=='및 '! ='은 참조로 비교됩니다. 참조로 비교하지 않도록 재정의 해야하는 경우 해당 코드를 숙독하는 다른 개발자에게는 명백하지 않은 일반 연산자 불일치를 만듭니다. "이 두 인스턴스의 상태가 동일합니까?"라는 질문을하려는 경우 IEquatible을 구현하고 Equals ()를 정의하고 해당 메소드 호출을 사용해야합니다.

마지막으로, IEquatable ()은 동일한 이유에 대해 NotEquals ()를 정의하지 않습니다. 동등 연산자 불일치를 열 가능성이 있습니다. NotEquals ()는 항상! Equals ()를 반환해야합니다. NotEquals ()의 정의를 Equals ()를 구현하는 클래스로 열어서 평등을 결정할 때 일관성 문제를 다시 한 번 강요합니다.

편집 : 이것은 단순히 내 추리입니다.


이것은 비논리적입니다. 그 이유가 일관성이라면 반대의 경우가 적용됩니다. 구현할 수 operator ==있고 컴파일러가 유추 할 것 operator !=입니다. 결국,이 그것을 위해하는 것입니다 operator +operator +=.
Konrad Rudolph

1
foo + = 바; foo = foo + bar;의 약어 인 복합 할당입니다. 연산자가 아닙니다.
blenderfreaky

그들은 참으로하면 된다 '항상 참 반대가', 그 이유가 될 것이다 자동으로 정의 a != b!(a == b)(C #은하지 않습니다 무엇이다) ....
andrewf

-3

아마 그들이 생각하지 않은 것은 할 시간이 없었을 것입니다.

==를 오버로드 할 때 항상 메서드를 사용합니다. 그런 다음 다른 하나에서 사용합니다.

적은 양의 작업으로 컴파일러가 이것을 무료로 제공 할 수 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.