C #의 암시 적 유형 변환 연산자는 언제 사용해야합니까?


14

C #에서는 다음과 같은 암시 적 변환 연산자를 오버로드 할 수 있습니다 ( MSDN의 예 ).

struct Digit
{
    /* ... */
    public static implicit operator byte(Digit d)  // implicit digit to byte conversion operator
    {
        /* ... */
    }
}

따라서 사용자 정의 값 유형유형을 사용 하여 마술처럼 자신을 다른 (관련되지 않은) 유형으로 변환하여 청중을 당황하게 만들 수 있습니다 (백 스테이지로 피어링하고 암시 적 변환 연산자를 볼 때까지).

나는 내 코드를 읽는 사람을 당황하게 만드는 것을 좋아하지 않습니다. 나는 많은 사람들이 그렇게 생각하지 않습니다.

문제는 내 코드를 이해하기 어렵게 만드는 암시 적 유형 변환 연산자의 사용 사례는 무엇입니까?


1
와. 나는 이것이 실제로 존재하는지 몰랐다. 반드시 사용하는 것이 좋은 것은 아닙니다. 나는 사람들이 C ++에서 이런 종류의 기능 숨기기에 정말로 화가 났음을 알고있다.
Katana314

@ Katana314 : 사람들이 짜증나게하는 것이 아니라 놀라운 행동, 바람직하게는 미묘하게 과부하가있는 과부하 (연산자, 변환 함수, 생성자, 자유 함수 또는 멤버 함수)를 추가하는 사람에 관한 것입니다.
중복 제거기

C ++에서 "연산자 오버로드", 특히 "캐스팅"연산자를 읽어 보는 것이 좋습니다. C #이 더 많이 읽을 수있는 한 토론이 세 번 진행되었다는 점을 제외하고는 /에 대한 동일한 주장 중 많은 부분이 동일하다고 생각합니다.

답변:


18

동일한 값을 다른 방식으로 나타내는 유형 간의 암시 적 변환 만 권장합니다. 예를 들어 :

  • 다른 색상의 종류가 좋아 RGB, HSL, HSVCMYK.
  • 동일한 물리량에 대한 다른 단위 ( Metervs Inch).
  • 다른 좌표계 (극성 대 직교).

그러나 암시 적 변환을 정의하는 것이 적절 하지 않은 시기를 나타내는 몇 가지 강력한 지침이 있습니다 .

  • 변환으로 인해 정밀도 또는 범위가 크게 손실되면 암시 적이 지 않아야합니다 (예 : float64에서 float32로 또는 long에서 int로).
  • 변환이 ( InvalidCast) 예외를 throw 할 수 있으면 암시 적이 어서는 안됩니다.
  • 변환이 수행 될 때마다 힙 할당이 발생하는 경우 암시 적이 어서는 안됩니다.
  • 변환이 O(1)조작이 아닌 경우 암시 적이 어서는 안됩니다.
  • 소스 유형 또는 대상 유형이 변경 가능한 경우 변환이 암시 적이 지 않아야합니다.
  • 변환이 어떤 종류의 컨텍스트 (데이터베이스, 문화권 설정, 구성, 파일 시스템 등)에 의존하는 경우 암시 적이 지 않아야합니다 (이 경우 명시 적 변환 연산자도 권장하지 않습니다).

이제 전환 연산자 f: T1 -> T2가 위의 규칙을 위반하지 않으면 다음 동작은 전환이 암시적일 수 있음을 나타냅니다.

  • 만약 a == b다음 f(a) == f(b).
  • 만약 a != b다음 f(a) != f(b).
  • 만약 a.ToString() == b.ToString()다음 f(a).ToString() == f(b).ToString().
  • 등 모두에 정의 된 다른 작업 T1T2.

귀하의 모든 예는 아마도 손실되었을 것입니다. 그것들이 어쨌든 충분히 정확한지, ...
중복 제거기

그래, 나는 깨달았다 :-). 나는 "손실"에 대한 더 나은 용어를 생각할 수 없었다. "손실"이라는 의미는 범위 나 정밀도가 크게 감소 된 전환입니다. 예를 들어 float64에서 float32로 또는 long에서 int로.
Elian Ebbing

나는 a! = b => f (a)! = f (b), 아마도 적용해서는 안된다고 생각합니다. 다른 입력에 대해 동일한 값을 반환 할 수있는 함수가 많이 있습니다. floor () 및 ceil () 예를 들어 수학 쪽
cdkMoose

@cdkMoose 물론 그렇기 때문에 이러한 속성을 규칙이 아니라 "보너스 포인트"로 더 많이 볼 수 있습니다. 두 번째 속성은 단순히 변환 함수가 주입 적이라는 것을 의미합니다. int32에서 int64로 범위가 더 큰 유형으로 변환하는 경우가 종종 있습니다.
Elian Ebbing

@cdkMoose 반면에, 첫 번째 속성은 동일한 동등성 클래스 내에있는 두 개의 값 T1(의 ==관계에 의해 암시 됨 T1)이 항상 같은 동등성 클래스 내에있는 두 개의 값에 매핑된다는 것을 나타 T2냅니다. 이제 그것에 대해 생각하기 때문에 첫 번째 속성이 실제로 암시 적 변환에 필요하다고 생각합니다.
Elian Ebbing

6

문제는 내 코드를 이해하기 어렵게 만드는 암시 적 유형 변환 연산자의 사용 사례는 무엇입니까?

유형 프로그래머와 관련이없는 경우 두 가지 관련되지 않은 유형 (코드에 관한 한)이 있고 실제로 관련된 (도메인 또는 합리적인 프로그래머의 경우) 관련된 (희소 한) 시나리오가 있습니다.

예를 들어, 일부 코드는 문자열 일치를 수행합니다. 일반적인 시나리오는 문자열 리터럴을 일치시키는 것입니다. 을 호출하는 대신 IsMatch(input, new Literal("some string"))암시 적 변환을 통해 코드에서 발생하는 잡음을 제거하고 문자열 리터럴에 집중할 수 있습니다.

대부분의 프로그래머 IsMatch(input, "some string")는 진행중인 작업을 보고 신속하게 직감 할 것입니다. 호출 사이트에서 코드를 명확하게 만듭니다. 즉, 그것은 좀 더 쉽게 이해할 수 있습니다 무엇 에 약간의 비용으로 진행되고 어떻게 그 일이 벌어지고.

이제 동일한 기능을 수행하는 간단한 함수 과부하가 더 좋을 것이라고 주장 할 수 있습니다. 그리고 그건. 그러나 이런 종류의 것이 어디에나 존재한다면, 함수 오버로드를 수행하는 것보다 하나의 변환이 더 깔끔합니다 (코드가 적고 일관성이 향상됨).

그리고 프로그래머가 "실제로 무슨 일이 일어나고 있는지"를 볼 수 있도록 중간 유형을 명시 적으로 작성하도록 요구하는 것이 낫다고 주장 할 수 있습니다. 덜 간단합니다. 개인적으로, 리터럴 문자열 일치 예제는 "실제로 진행되고있는 일"에 대해 매우 분명하다고 생각합니다. 프로그래머는 모든 일 이 어떻게 일어나는지에 대한 메커니즘을 알 필요가 없습니다 . 코드가 실행되는 다양한 프로세서에서 모든 코드가 어떻게 실행되는지 알고 있습니까? 프로그래머는 무언가가 어떻게 작동 하는지 신경 쓰지 않는 추상화 라인이 항상 있습니다. 암시 적 변환 단계가 중요하다고 생각되면 암시 적 변환을 사용하지 마십시오. 그들이 컴퓨터를 행복하게 유지하기위한 행사 일 뿐이라고 생각한다면 프로그래머는 어디서나 그 소음을 보지 않는 것이 좋습니다.


마지막 요점은 더 나아가 야합니다. 프로그래머가 무언가를 어떻게하는지 잘 신경 쓰지 않는 선이 있습니다. 계약이 아니기 때문입니다.
중복 제거기
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.