모든 설계 프로세스는 서로 호환되지 않는 목표간에 타협을 초래합니다. 불행히도 &&
C ++에서 오버로드 된 운영자를 위한 설계 프로세스 는 혼란스러운 최종 결과를 &&
낳았습니다. 단락 동작 에서 원하는 기능 은 생략되었습니다.
그 디자인 프로세스에 대한 세부 사항은 내가 알지 못하는 불행한 곳에서 끝났습니다. 그러나 나중의 설계 프로세스가 어떻게이 불쾌한 결과를 고려했는지를 보는 것이 적절합니다. C #에서 오버로드 된 &&
작업자 가 단락되었습니다. C #의 디자이너는 어떻게 그것을 달성 했습니까?
다른 답변 중 하나는 "람다 리프팅"을 제안합니다. 그건:
A && B
도덕적으로 동등한 것으로 실현 될 수 있습니다.
operator_&& ( A, ()=> B )
여기서 두 번째 논증은 평가할 때 부작용과 표현의 가치가 만들어 지도록 게으른 평가를위한 메커니즘을 사용합니다. 오버로드 된 연산자의 구현은 필요한 경우에만 지연 평가를 수행합니다.
이것이 C # 디자인 팀이 한 것이 아닙니다. (옆으로 : 람다 리프팅 은 연산자 의 표현 트리 표현 을 할 때 내가 한 일이지만 ??
, 일부 변환 작업은 느리게 수행해야합니다. 그러나 자세하게 설명하는 것은 큰 혼란이 될 것입니다. 작동하지만 우리가 그것을 피하기에 충분히 무겁습니다.)
오히려 C # 솔루션은 문제를 두 가지 별도의 문제로 나눕니다.
- 오른쪽 피연산자를 평가해야합니까?
- 위의 대답이 "예"라면 두 피연산자를 어떻게 결합합니까?
따라서 &&
직접 과부하 되는 것을 불법으로하여 문제를 해결 합니다. 오히려 C # 에서는 두 개의 연산자 를 오버로드해야합니다 . 각 연산자는이 두 가지 질문 중 하나에 응답합니다.
class C
{
// Is this thing "false-ish"? If yes, we can skip computing the right
// hand size of an &&
public static bool operator false (C c) { whatever }
// If we didn't skip the RHS, how do we combine them?
public static C operator & (C left, C right) { whatever }
...
(실제로 세 개. C #에서는 연산자 false
가 제공 되면 연산자 도 제공 true
해야하며,이 질문에 대한 답은 "진정한가?"라는 질문에 대답해야합니다. 둘 다 필요합니다.)
다음 형식의 진술을 고려하십시오.
C cresult = cleft && cright;
컴파일러는이 의사 C #을 작성했다고 생각한대로 이에 대한 코드를 생성합니다.
C cresult;
C tempLeft = cleft;
cresult = C.false(tempLeft) ? tempLeft : C.&(tempLeft, cright);
보다시피, 왼쪽은 항상 평가됩니다. "거짓"인 것으로 판단되면 결과입니다. 그렇지 않으면 오른쪽이 평가되고 열성적인 사용자 정의 연산자 &
가 호출됩니다.
||
오퍼레이터는 오퍼레이터의 호출에 해당하고 싶어 같이 유사한 방식으로 정의된다 |
연산자
cresult = C.true(tempLeft) ? tempLeft : C.|(tempLeft , cright);
네 개의 연산자를 정의하여 - true
, false
, &
와 |
- C #을 당신이 말을뿐만 아니라 수 있습니다 cleft && cright
비 단락뿐만 아니라 cleft & cright
, 또한 if (cleft) if (cright) ...
, 및 c ? consequence : alternative
과 while(c)
, 등등.
이제 모든 설계 프로세스가 타협의 결과라고 말했습니다. 여기서 C # 언어 디자이너는 단락 &&
을 ||
올바르게 처리했지만 두 사람 대신 네 명의 연산자를 오버로드해야하므로 일부 사람들은 혼란스러워합니다. 연산자 true / false 기능은 C #에서 가장 잘 이해되지 않은 기능 중 하나입니다. C ++ 사용자에게 친숙하고 직관적 인 언어를 사용한다는 목표는 단락을 원하고 람다 리프팅 또는 다른 형태의 게으른 평가를 구현하지 않으려는 욕구에 반대했습니다. 그게 합리적인 타협 위치라고 생각하지만, 그것을 실현하는 것이 중요 하다 타협 위치입니다. 그냥 다른 C ++의 설계자가 착륙 한 것보다 위치를 타협하십시오.
그러한 연산자에 대한 언어 디자인의 주제에 관심이 있다면 C #이 이러한 연산자를 nullable 부울에 정의하지 않는 이유에 대한 시리즈를 읽으십시오.
http://ericlippert.com/2012/03/26/null-is-not-false-part-one/
operator&&(const Foo& lhs, const Foo& rhs) : (lhs.bars == 0)