Microsoft MVP성태의 닷넷 이야기
패턴매칭 -튜퓰비교에 관한 오류사항과 궁금증 [링크 복사], [링크+제목 복사],
조회: 6711
글쓴 사람
카짜프로그래머
홈페이지
첨부 파일
(연관된 글이 1개 있습니다.)

안녕하세요.

769P, 852P의 switch문에 에 보면

case var r when r.Equals((0,0)):

부분이 있는데요.

여기에서 Equals()안의 (0,0)은 튜플인 것으로 확인했습니다. 앞선 설명에서 튜플의 이런 형태에대한 언급은 없어 의문이 들긴 했지만 어쨌든 VS에서 확인해보니 맞네요.


 769P 에서의 경우

Action<T>의 T가 튜플인 (int,int)이기때문에 람다식에있는 arg 변수는 그와 같은 튜플이므로

r.Equals((0,0)) 은 튜플.Equals(튜플)로 같은 튜플끼리의 비교라서 문제는 없습니다

그런데 852P의 속성패턴에 앞선 예시로 다시한번 r.Equals((0,0)) 이 나오는데요.

이때는 Func<T, TResult>의 T 가 Point 타입인 관계로 람다식과 switch의 pt는 Point 타입이죠.
(별개로 VS에서 돌려보니 여기에 쓰인 pt는 아래쪽 Point 인스턴스 식별자 pt와 이름이 같으면 안된다고 해서 저는 obj라는 이름으로 바꿨습니다.)

그 결과 r.Equals((0,0)) 은 Point인스턴스.Equals(튜플) 로,
Equals가 사용자정의 타입과 튜플(정확히는 그것의 속성과 요소)을 비교하는데 쓰이게된다는데(적어도 책에서는 그러하게보임) 주목하고 의문이 꼬리에 꼬리를 물게 되었네요.

RUN해본 결과 852P에서의
case var r when r.Equals((0,0)):
부분은
Point pt = new Point { X = 0, Y = 0 };
으로 하더라도 참이 되지 않더군요.

이걸 추적하고 이해하려는 과정에서 여러가지 의문들이 생기는데 질문들이 정리는 안되고 이렇게 글로 쓰고 있습니다.


서로다른 타입의 객체를 비교하는데 오류가 나지 않았다는 것.
=> 저에게 많은 혼란을 줬는데 C#의 Equals()에대한 이해가 없어서 인 것같습니다.


Point 정의에서 ToString()을 오버라이딩 한 것
=> 이것은 현재의 코드상으로는 case문 판단에 어떠한 영향도 주고 있지않지만 굳이 오버라이딩 했기때문에 유심히 보았는데 튜플형태의 문자열로 오버라이딩 하셨더군요.
그래서

문자열.Equals(문자열)

같은 방식이 아닐까 싶기도 했습니다만
이런 ToString() 오버라이딩은 Point인스턴스 자체를 출력했을 때 (0,0)처럼 나오기는 하지만 객체상으론 문자열은 아니므로 VS에서 r은 문자열이 아닌 {(0,0)}로 나옵니다.
()안의 튜플은 (int, int) 이고요.
그래서 ToString()을 사용해서 뭘 하려했던게 아니었나 싶습니다.
하여간 저 case가 의도대로 작동하려면
r.ToString().Equals((0,0).ToString())
이라거나
855P 위치패턴처럼
switch (pt.x, pt.y)
같은식으로 되어야겠죠.
하지만 이런식으로 생각하다보면 여러가지 방법들이 나올테니 생각하기를 그만두었습니다.
원래의 의도가 무었이었는지 묻는게 빠르겠죠. 아니면 제가 생각하지 못한 뭔가가 저 예시에 있는지 알고싶습니다.


그리고 속성패턴의 사용법 설명을 위한 case이긴하겠지만, 앞서 " Point 인스턴스 값 중에서 0이 있는지 확인하는 메서드 구현"이라는 구문은
논리적으로
case var r when r.Equals((0,0)):
처럼 둘다 0,0인지 비교(AND)하는 구문은 필요없다고 느껴집니다. 어차피 pt1.x == 0 와 pt2.y == 0 만 하는 것으로도 충분하니까요
이 또한 Equals()의 기능인가? 라는 생각이 들긴했지만 그 이름과 다른곳에서의 사용에서 직감적으로 그건 아니라고 생각하게 해주는군요.


이 뒤에 속성패턴을 이해하는데 중요하거나 문제가 있는 것은 아니었으나 이로인해 많은 혼란을 주기에 뭔가 정리를 해주셨으면 합니다.



[연관 글]






[최초 등록일: ]
[최종 수정일: 12/7/2021]


비밀번호

댓글 작성자
 



2021-12-07 10시32분
결론을 먼저 말하면, 두 번째 예제가 잘못된 것입니다. (앞선 예제를 그대로 활용하다 보니 그런 오류가 포함된 것입니다.)

하나씩 정리해 드리겠습니다.

1) 769 페이지의 Tuple 사용예는 사실 앞선 "12.3 튜플" 절에서 나옵니다. 가령 749 페이지의 ParseInteger 메서드의 반환 유형에서도 (result, Number)와 같이 쓰이고 있습니다. (단순히 숫자 리터럴을 사용하지 않은 차이 정도입니다.)

2) 그리고, 852 페이지에서의 예제에서 Equals가 서로 다른 타입인데도 오류가 발생하지 않은 것은, Equals가 받아들이는 타입이 object이기 때문입니다. 그래서 Tuple 타입을 전달해도 컴파일 오류가 발생하지 않았지만, 일단 내부 구현에서는 타입이 다르므로 무조건 그런 경우에는 false를 반환하게 됩니다.

3) 예상하신대로 ToString은 단순히 보기 편한 문자열을 생산하는 용도로 정의해 둔 것입니다. (Tuple의 동작에는 어떠한 영향도 미치지 않습니다.)

4) 말씀하신대로 AND 비교는 필요 없습니다. 단지 예로 든 F#의 예제 코드에서 그것까지 포함하고 있기 때문에 예제 차원에서 그렇게 유지한 것입니다. 하지만 그리 중요하게 고수할 필요는 없으니 빼는 것이 맞다고 보고, 그럼으로써 필요 없는 혼란도 없앨 수 있겠습니다.

------------------------------------

간단한 예제 하나로 너무 많은 혼란을 주어 죄송하고, 아울러 의견 주셔서 감사합니다. 관련해서는 정오표에 추가했고,

https://www.sysnet.pe.kr/2/0/12408#errata

다음 인쇄부터는 수정해서 발행될 것입니다.
정성태

... 31  32  33  34  35  36  [37]  38  39  40  41  42  43  44  45  ...
NoWriterDateCnt.TitleFile(s)
4936무개1/3/20189015책 내용 인용하는 것에 관한 질문이있습니다. [1]파일 다운로드1
4935몬난아12/28/201711744IIS 및 ASP.NET 이 서버에서의 동작방식? [2]
4934Ques...12/26/201722185C# 해상도에 따른 자동 사이즈 조절방법이 궁금합니다. [3]
4933Kay12/15/20179437C# VS 버전 에러 질문 드립니다. [1]파일 다운로드1
4932정환나라12/13/20179338vs2013에서 빌드한 com 컨트롤 객체를 닷넷 2.0에서 사용하려 합니다 [4]
4931Arvid12/12/201710430Visual Studio 2012 c# using문 참조 에러 [5]파일 다운로드1
4929김성대12/8/20178844app.config에 관한질문입니다. [1]
4928김성대12/7/20179476SQL Server 설치에러에 대한 질문입니다. [1]파일 다운로드1
4926heyh...12/6/20178743[삭제] ContextSwitchDeadlock????
4925ho12/5/20179280[삭제] WebBrowser로 드롭박스 로그인 페이지 탐색 시 발생한 문제에 대해 질문 올립니다.파일 다운로드2
4924몽중언12/3/20179692C# 디버깅 모드에서만 DB Insert가 되는 현상 질의 [6]
4923고요한11/23/20179797파일 확장자에 연결된 프로그램을 등록하는 방법에 대한 질문입니다. [2]
4922박성훈11/23/201710765시작하세요! C# 7.1 학습 방법 [3]
4921초보개발자11/20/20177993[삭제] 폼 사이즈 질문드립니다.
4920Ques...11/19/20179140IEnumerable 의 "지연된 평가" 에 관하여 질문드립니다. [2]파일 다운로드1
4919mskim11/16/20179458Split()을 이용하여 문자 구분 시 구분문자도 같이 저장하는 방법이 있나요? [2]
4917ho11/16/201710055WPF XAML 트리거 관련해 문의 드립니다. [3]
4918ho11/16/201710352    답변글 [답변]: 예제 프로젝트 첨부합니다. [4]파일 다운로드2
4916필승11/11/201710027기본 웹 브라우저 체크는 어떻게 해야 하나요? [2]
4915필승11/10/20179105WebBrowser 컨트롤 소리 출력 문의 드립니다. [2]
4914Ques...11/10/20179788c# 버튼 이벤트에 관하여 질문드립니다. [2]
4913Arvid11/8/201712233Log4Net 라이브러리를 이용하여 특정 기간이 지났을 때 자동 로그 삭제 기능 구현 질문 드립니다! [2]
4912조범희11/8/201711912C# FTP 다운로드중 에러 발생.. [2]파일 다운로드1
4911필승11/6/201710323WebBrowser 컨트롤 사용법에 대해 궁금합니다. [2]
4910진우11/6/20179897람다 초보 질문 드립니다. [2]
4909필승11/5/201710787TextBox에 관해 질문 드립니다. [5]
... 31  32  33  34  35  36  [37]  38  39  40  41  42  43  44  45  ...