문제

실패 :

object o = ((1==2) ? 1 : "test");

성공 :

object o;
if (1 == 2)
{
    o = 1;
}
else
{
    o = "test";
}

첫 번째 진술의 오류는 다음과 같습니다.

'int'와 'string'사이에 암시 적 변환이 없기 때문에 조건부 표현의 유형을 결정할 수 없습니다.

그래도 왜 그 값을 유형 객체의 변수에 할당하고 있습니다.

편집하다: 위의 예는 사소한 것이지만, 이것이 매우 도움이되는 예가 있습니다.

int? subscriptionID; // comes in as a parameter

EntityParameter p1 = new EntityParameter("SubscriptionID", DbType.Int32)
{
    Value = ((subscriptionID == null) ? DBNull.Value : subscriptionID),
}
도움이 되었습니까?

해결책

사용:

object o = ((1==2) ? (object)1 : "test");

문제는 조건부 연산자의 반환 유형을 불쾌하게 결정할 수 없다는 것입니다. 즉, INT와 String 사이에는 최선의 선택이 없습니다. 컴파일러는 항상 진정한 표현의 유형을 사용하고 필요한 경우 거짓 표현식을 암시 적으로 시전합니다.

편집하다:두 번째 예에서 :

int? subscriptionID; // comes in as a parameter

EntityParameter p1 = new EntityParameter("SubscriptionID", DbType.Int32)
{
    Value = subscriptionID.HasValue ? (object)subscriptionID : DBNull.Value,
}

추신:
그것은 '제 3의 운영자'라고 불리지 않습니다. 그것 ~이다 3 원 운영자이지만 '조건부 운영자'라고합니다.

다른 팁

다른 대답은 있지만 옳은, 그들이 진실하고 관련성있는 진술을한다는 의미에서, 여기에는 아직 표현되지 않은 미묘한 언어 디자인이 있습니다. 여러 가지 요인이 조건부 연산자의 현재 설계에 기여합니다.

첫째, 표현의 내용 으로부터만 결정될 수있는 모호하지 않은 유형을 가질 수있는 가능한 많은 표현이 바람직하다. 이것은 몇 가지 이유로 바람직합니다. 예를 들어 : Intellisense 엔진을 훨씬 쉽게 구축 할 수 있습니다. 당신은 입력합니다 x.M(some-expression. 그리고 Intellisense는 분석 할 수 있어야합니다 약간의 표현, Intellisense가 XM이 무엇을 의미하는지 알기 전에 유형을 결정하고 드롭 다운을 생성합니다. IntelliSense는 XM이 모든 인수를 볼 때까지 M이 과부하되는지 확실히 말하는 것을 알 수 없지만 아직 첫 번째 인수조차도 입력하지 않았습니다.

둘째, 방금 언급 한 시나리오 : 과부하 해상도로 인해 "내부에서 외부로"유형 정보가 유형 정보를 선호합니다. 다음을 고려하세요:

void M(object x) {}
void M(int x) {}
void M(string x) {}
...
M(b ? 1 : "hello");

이것이 무엇을해야합니까? 객체 오버로드를 부르야합니까? 때때로 문자열 과부하를 호출하고 때로는 int 오버로드를 호출해야합니까? 다른 과부하가 있다면 어떨까요? M(IComparable x) - 언제 선택합니까?

유형 정보가 "두 가지 방식으로 흐르면"상황이 매우 복잡해집니다. "이 물건을 유형 객체의 변수에 할당하고 있으므로 컴파일러는 유형이 씻지 않기 때문에 객체를 선택해도 괜찮다는 것을 알아야합니다. 종종 그렇습니다 우리는 당신이 할당하는 변수의 유형을 모릅니다. 그것이 우리가 알아 내려고하는 과정에 있기 때문입니다.. 오버로드 해상도는 인수 유형에서 인수를 할당하는 변수 인 매개 변수의 유형을 해결하는 프로세스입니다. 인수의 유형이 할당 된 유형에 의존한다면, 우리는 추론에 원형이 있습니다.

유형 정보는 Lambda 표현식의 경우 "두 가지 방식으로 흐릅니다". 그것을 효율적으로 구현하면 1 년의 더 나은 부분이 필요했습니다. 나는 표현식이 사용되는 컨텍스트를 기반으로 유형 정보가 복잡한 표현식으로 흐르는 분석을 수행 할 수있는 컴파일러를 설계하고 구현하는 데 어려움을 묘사하는 몇 가지 일련의 기사를 작성했습니다. 1 부가 여기에 있습니다.

http://blogs.msdn.com/ericlippert/archive/2007/01/10/lambda-expressions-vs-anonymous-methods-part-on.aspx

"음, 알았어, 내가 객체에 할당한다는 사실을 컴파일러에서 안전하게 사용할 수없고, 표현이 명확하게 유형을 가질 필요가있는 이유를 알 수 있지만 왜 유형이 아닌 이유를 알 수있다. int와 문자열이 객체로 변환 될 수 있으므로 표현 객체의 경우? " 이것은 나의 세 번째 요점으로 나를 데려옵니다.

셋째, C#의 미묘하지만 일관되게 적용되는 디자인 원칙 중 하나는 "마법으로 유형을 생산하지 마십시오"입니다. 유형을 결정 해야하는 표현 목록이 주어지면 우리가 결정한 유형은 항상 어딘가에 목록에 있습니다.. 우리는 결코 새로운 유형을 마술로 마술을 마치고 당신을 위해 그것을 선택합니다. 당신이 얻는 유형은 항상 당신이 우리에게 선택한 유형입니다. 유형 세트에서 가장 좋은 유형을 찾으려면 해당 유형 세트에서 가장 좋은 유형을 찾습니다. {int, string} 세트에는 "동물, 거북이, 포유류, 왈라비"에 가장 좋은 공통 유형이 없습니다. 이 설계 결정은 조건부 연산자에게 적용, 통일 시나리오를 입력하고 암시 적으로 입력 한 배열 유형의 추론 등에 적용됩니다.

이 설계 결정의 이유는 평범한 인간이 최상의 유형을 결정 해야하는 특정 상황에서 컴파일러가 무엇을할지 쉽게 해결할 수 있기 때문입니다. 얼굴을 쳐다보고있는 유형이 선택 될 것이라는 것을 알고 있다면 어떤 일이 일어날 지 알아내는 것이 훨씬 쉽습니다.

또한 충돌이있을 때 가장 일반적인 유형의 유형이 무엇인지에 대한 많은 복잡한 규칙을 해결해야합니다. {foo, bar} 유형이 있다고 가정합니다. 가장 공통적 인 유형 인 Iblah는 둘 다 확장되는 BAZ 또는 BAZ를 모두 구현하는 것은 무엇입니까? 우리는이 질문에 대답하고 싶지 않습니다. 우리는 그것을 완전히 피하고 싶습니다.

마지막으로, C# 컴파일러는 실제로 일부 모호한 경우에서 미묘하게 잘못된 유형의 결정을 얻습니다. 그것에 대한 첫 번째 기사는 여기에 있습니다.

http://blogs.msdn.com/ericlippert/archive/2006/05/24/type-inference-woese-part-on.aspx

실제로 컴파일러가 올바르게 수행하고 사양이 잘못되었다고 주장 할 수 있습니다. 구현 디자인은 사양 디자인보다 제 생각에 더 좋습니다.

어쨌든, 그것은 3 원 운영자 의이 특정 측면을 설계 한 몇 가지 이유 일뿐입니다. 예를 들어, CLR 검증기가 주어진 분기 경로 세트가 가능한 모든 경로에서 스택에 올바른 유형을 남기도록 보장되는지를 결정하는 방법과 같은 다른 미묘함이 있습니다. 자세히 논의하면 다소 멀리 떨어져있을 것입니다.

기능 X이 방식이 왜 대답하기 어려운 질문입니다. 실제 행동에 대답하는 것이 훨씬 쉽습니다.

이유에 대한 나의 교육받은 추측. 조건부 연산자는 두 가지 관련 값 중에서 선택하기 위해 부울 표현식을 간결하게 사용하고 간결하게 사용하도록 허용됩니다. 그들은 단일 위치에서 사용되기 때문에 관련되어 있어야합니다. 사용자가 대신 2 개의 관련없는 값을 선택하면 코드에 미묘한 오타 / 버그가 있었고 컴파일러는 암시 적으로 객체에 캐스팅하는 것이 아니라 이에 대해 경고하는 것이 좋습니다. 그들이 기대하지 않은 것일 수 있습니다.

"int"는 객체가 아닌 원시 유형이며 "문자열"은 "원시 물체"로 간주됩니다. "Object O = 1"과 같은 일을하면 실제로 "int"를 "int32"로 권투하고 있습니다. 권투에 관한 기사에 대한 링크는 다음과 같습니다.

http://msdn.microsoft.com/en-us/magazine/cc301569.aspx

일반적으로 추적하기 어려운 성능 손실로 인해 권투를 피해야합니다.

3 배 표현식을 사용하면 컴파일러는 할당 변수를 전혀 보지 않아 최종 유형이 무엇인지 결정하지 않습니다. 원래 진술을 컴파일러가하는 일로 분류하려면 다음과 같습니다.

명령문 : Object o = ((1 == 2)? 1 : "테스트");

컴파일러:

  1. "1"및 "test"in '((1 == 2)? 1 : "test")의 유형은 무엇입니까? 그들은 일치합니까?
  2. #1의 최종 유형이 'Object O'의 할당 연산자 유형과 일치합니까?

컴파일러는 #1이 완료 될 때까지 #2를 평가하지 않으므로 실패합니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top