2015-01-13 5 views
23

C# 6.0의 새로운 (제안 된) 기능 중 일부가 해결 된 흥미로운 사이트를 발견했습니다. 여기에서 읽을 수 있습니다 : Probable C# 6.0 features.C# 6.0 모나드 널 검사

흥미로운 것은 모나드 널 검사 (null 전파 연산자 ?라고도 함)입니다.

if (points != null) 
{ 
    var next = points.FirstOrDefault(); 
    if (next != null && next.X != null) return next.X; 
} 
return -1; 

가 내 첫 눈이, 이봐, 도대체가 기록되었다 : 현재이 코드 조각으로 구현되는 사이트,

var bestValue = points?.FirstOrDefault()?.X ?? -1; 

는 모나드 널 체크를 포함하는 다음과 같은 성명에 따르면, 이리? 그러나 '오래된'코드를 살펴본 후, 나는 그것을 좋아하기 시작했습니다.

그러나 나는 또한 물어보고 싶은 몇 가지 질문을하기 시작했습니다.

  • 이 null 전파 연산자는 스레드로부터 안전하다고 가정합니다. 그러나 실제로 어떻게 수행됩니까? 경쟁 조건이 제거되거나 지속될 것입니까?
  • 이 연산자는 제네릭 형식을 어떻게 처리합니까? 또한 제약이없는 제네릭 형식은 어떻게 처리할까요? 유형 여기 Y는 참조 유형, 비 - 널 (NULL) 값 유형 및 널 (NULL) 값 형식 인스턴스화하는 경우 예를 들어, 내가 무엇을해야하는지 생각할 수있는만큼, (할 수있는 합리적인 아무것도 없을 것이다,

    var resultAfterNullCheck = x?.Y; 
    

    을 고려 나는 단순히 무엇을 해야할지 모른다.) 그래서 거기에 반환됩니다 기본값은 무엇입니까? 아니면 오류가 발생합니까?

  • 사이트에서 제공하는 (그리고 위에서 복사 한) 예제를 보면 널 전파 연산자의 주요 이점 중 하나는 명령문을 한 번만 평가할 것이라고 가정합니다. 그러나 (아마 CLR에 대한 지식이 부족하여) 어떻게 수행 할 수 있는지 궁금합니다.
    나에 관해서는 첫 번째 평가 (points가 null 인 경우)는 points가 null이 아닌 경우 확장 메서드 인 FirstOrDefault()를 트리거하고 반환 된 유형의 평가가 null이거나 그렇지 않으면 X가되도록 트리거해야합니다 반환됩니다. 그래서 이것들은 실제로 하나의 평가와 결합 된 3 가지 평가입니까? 아니면 잘못 이해하고 있습니까? 이것이 실행 속도에 영향을 줍니까?

즉, 더 빠른 방법, 오래된 검사 수행 방법 또는이 새로운 멋진 연산자는 무엇입니까? 나는 Visual Studio 2015 다운로드가 끝나자 마자 연구를 수행하여 이것을 조사하려고 노력할 것입니다 ... 그러나 그것은 약간의 인내가 필요합니다 ...

이 새로운 운영자 유형에 대한 의견이 있습니까? 정말 여전히 제안 된 것입니까, 아니면이 새로운 모나드 검사로 실제로 작업 할 수 있습니까? 이 제약 제네릭과 어떻게이 운영자 거래에 관한 내 이전 질문을 언급 한 경우

편집
매튜 왓슨 제공으로 좋은 MSDN article이 (더) 주제 (들) 논의가 궁금했다. 불행히도 아직 답변을 찾지 못했습니다. 프로그래머가 제약없는 제네릭의 사용을 막으려 고 노력해야한다고 가정하지만, 때로는 실현 가능성이 없다고 생각할 수도 있습니다. 그렇다면 재 설계가 정말로 필요할까요?

+2

[Null 조건부 연산자] (http://blogs.msdn.com/b/csharpfaq/archive/2014/11/20/new-features-in-c-6.aspx)라고합니다. –

+1

많은 정보는 https://roslyn.codeplex.com/discussions/540883에서 확인할 수 있습니다. – adrianm

+2

@MatthewWatson'if (MyEvent! = null) MyEvent (this, EventArgs.Empty);는'var myEvent = MyEvent;로 다시 써야하는 것의 잘 알려진 예입니다. if (myEvent! = null) myEvent (this, EventArgs.Empty);': MyEvent'에 대한 액세스가 아톰 인 경우에도 비교와 호출 사이에 null이 아닌 null로 변경 될 수 있습니다. 그것은 'MyEvent? .Invoke (this, EventArgs.Empty);'가 이미 이해해야하는 것입니다. – hvd

답변

14

당신은이 것을 지나치게 생각하고 있습니다. 하나씩 질문 해주세요.

  1. 왜 스레드 안전하다고 가정합니까? 멤버 함수를 호출하는 것이 아닙니다. 이것은 널 (NULL)에 대한 사전 검사로 멤버 함수를 호출하는 것일 뿐이므로 원래 함수가 보증하는만큼의 스레드 안전성 만 얻습니다.

  2. 제네릭 형식이 null 비교 (이 연산자가 장면 뒤에서 사용할 것임)를 허용하는 경우 코드가 생성됩니다. 그렇지 않으면 컴파일 오류가 발생합니다 (예 : 유형이 값 유형이어야하는 경우). 그 모든 경우를 다룹니다!

  3. 보통 . 연산자와 마찬가지로 연산자 당 한 번 호출됩니다. 만약 당신이 A.b.c라고한다면, 그것은 간접적 인 두 수준이 될 것이고,이 새로운 연산자를 사용하는 것은 전혀 다르지 않을 것입니다, 그것은 단지 null도 체크합니다. ?.

실제 혜택이 의미 있다고하며, 단락이 (if의 중첩 된 것보다 훨씬 더 짧은 코드를 만드는) (당신은 당신의 코드가 시도되는 것을 한 눈에 알 수 있습니다). 이전 코드의 .을 모두 ?.으로 바꾸지는 않을 것입니다. 사실 거의 사용하지 않을 것입니다. 그러나, ...OrDefault() 작업이나 호출 이벤트를 따르는 Linq 표현식과 같이 유용 할 경우가 있습니다.

+3

정말 필요한가요? 나는 누군가가'x? .f'가 마술처럼'f' threadsafe를 만들 것을 기대하지 않는다고 생각합니다. 그는 단지'x? .f'가'if (x.f! = null) x.f'에서 경쟁 조건을 제거하는지 여부를 묻는 것입니다. – Rawling

+4

나는 그걸 들었을 때 나는 그것을 들었습니다. 제 아내조차도 그것에 대해 불평합니다. 나는 그것이 실제로 시도하기 전에 기계공이 어떻게 작동 하는지를 이해하려고 노력하고있는 것으로 생각합니다. @ Rawling은 첫 번째 질문에서 의미하는 바를 옳습니다. 내 질문을 수정하겠습니다. – RvdV79

+0

@Rawling, 나는 그럴 줄 알았지 만, 코드를 보면 변수가 스택에 먼저 저장되고 테스트 된 다음 사용 된 것을 이미 알고 있다는 것을 알 수 있습니다. – Blindy

6

부분적으로 첫 번째 질문에 대답하려면 (즉,이 비주얼 스튜디오 2013 < 작동을 의미) nuget 패키지처럼 로슬린를 사용하여 콘솔 응용 프로그램에 새로운 기능을 시도 할 수 있습니다 John Skeet on his blog에 따르면 null 조건부 연산자 ?. (= 전파 전파 연산자)은 스레드로부터 안전합니다.

+0

블로그 작성자가 스레드 안전을 위해 Interlocked.CompareExchange를 사용하는 경우 연산자 스레드가 안전합니까? 내 생각에 그럴 수도 있겠지만 언급 한 블로그 게시물에 그 증거가 보이지 않았다. 내가 놓친 게 있니? –

+1

"우리가 지금까지 가지고있는 코드는 다른 스레드가하는 일과 상관없이"thread-safe "합니다. 위의 코드에서 NullReferenceException을 얻지는 못할 것입니다."한편 Interlocked.CompareExchange는 유용합니다 "이벤트 구독자의 절대 최신 세트 호출". 따라서 스레드 안전성에 관한 것이 아니라 가장 최근의 이벤트 가입자 세트에서 이벤트가 실행되도록 보장 할 것인지 여부입니다. –

+0

연산자는 기본적으로 x를 취하고 null을 검사하며 null이 아닌 경우 x에서 다음 코드를 실행하는 메서드를 평가합니다. 멤버 변수를 사용하여 메서드를 호출하고 즉시 멤버 변수가 null로 설정된 경우 메서드의 변수에는 여전히 실제 개체가 있습니다. 이런 의미에서 ?. 스레드로부터 안전합니다. –