언어 디자이너를 위해 말할 수는 없지만 내가 추론 할 수있는 것은 의도적이고 적절한 디자인 결정 인 것 같습니다.
이 기본 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, 그러나 그것은 실제로 여기서 중요한 것은 아닙니다.