2017-02-16 15 views
3

this code 예를 들어 C# 7.0에 있었고이 루프의 성능과 성능에 대해 확신 할 수 없었습니다.C# 7을 사용하여 foreach 선언에서 Null- 합체 연산자

foreach (var c in text ?? throw new ArgumentNullException(nameof(text))) 
{ 
    ... 
} 

내 질문 :

  1. 조건부 문을 한 번 치거나 ( 각각의 반복에) 여러 번받을합니까?
  2. 새로운 구문이 다르게 보입니다. 이렇게하면 이점이 무엇입니까?
+5

테스트했을 때 성능에 어떤 영향을 줬습니까? 니가 그랬니? 자신의 질문에 대한 답을 스스로 이해하는 데 필요한 검사만으로는 충분하지 않은 이유를 설명하십시오. 정확하게 테스트 한 결과를 정확하게 보여주는 좋은 [mcve]가 포함되도록 질문을 수정하고 테스트에 대해 정확히 이해할 수없는 부분에 대한 자세한 설명을 포함하십시오. –

+2

번. 'text'가 null 인 경우, 조건문은 일단 히트됩니다. 설명 없이는 논리적이어야합니다. 반복하는 경우 열거자를 반복 할 때까지 한 번만 표시됩니다. –

+0

@PeterDuniho 질문의 틀이 어떻게 틀린 지 잘 모르겠습니다. – Svek

답변

2

될 것입니다 이 C# 기능을 이해하려면 foreach 내부 코드를 이해해야합니다. foreach 문에서 표현의 오른쪽 부분이 IEnumerable(<T>) 인터페이스를 구현해야하며, 전체 루프는 내부적으로이 같은 간단한 while, 뭔가 :

// here can be NullReferenceException 
var en = text.GetEnumerator(); 
while(en.MoveNext()) 
{ 
    var c = en.Current; 
    { 
     ... 
    } 
} 

당신이 볼 수 있듯이,이 코드의 포인트가되는 NRE

if (text.IsNullOrWhitespace()) 
{ 
    throw new ArgumentNullException(nameof(text)); 
} 

// while loop here or text.SomeLinqCodeHere() 

정말 필요하지 않습니다 여기에 몇 줄의 코드가 일부 엔트로피를 추가 :이 같은 열거 전에 전체 루프 또는 Enumerable extensions class를 확인해야하므로, 발생 진정한 가치는 없다. foreach 간단한 정말 의견을 기반 코드 표준에 대한 결정하지만,이 기능의 진정한 목적의 경우에는 다음과 같이 ?. operator 같은 C#7 다른 새로운 것을 함께 체인 경우 : 던지는 이러한 경우

int? length = customers?.Length ?? throw new ...; 
Customer first = customers?[0] ?? throw new ...; 
int? count = customers?[0]?.Orders?.Count() ?? throw new ...; 

예외는 코드 줄의 끝 부분에 언급 유사합니다

int? length = customers?.Length; // should not be null 
Customer first = customers?[0]; // should not be null 
int? count = customers?[0]?.Orders?.Count(); // should not be null 

을하지만 코드에 대한 몇 가지 엄격한 계약과 같은 규칙을 추가합니다.그런 식으로 foreach 루프의 성능에 관해서는

, 이미 말했듯이, 그것은 열거를 받고 한 번만 발생으로 고생하고 전에 실제 루프하지 않습니다.

9

"foreach 작동 방식"에서 조건문은 한 번만 계산됩니다.

당신은이 질문에 어떻게 작동하는지 foreach는 루프에 대한 자세한 내용을 할 수 있습니다

:
How do foreach loops work in C#?
Does foreach evaluate the array at every iteration?

감사를 Svek에 비주얼 스튜디오 이후에 출시 될 새로운 C# 7.0 기능이라고 설명하기위한 2017 RC :
http://structuredsight.com/2016/09/01/c-7-additions-throw-expressions/

"이점은 무엇인가"는 일종의 의견 기반 질문이라고 생각합니다.
제 의견으로는 좋은 점이 전혀 없으며 용어 또는 코드 가독성면에서보기 흉합니다.
내가 널리 사용되는 일반적인 좋은 연습 사용하는 것이 좋습니다 것입니다 : 아마

if (text == null) // or string.IsNullOrEmpty for strings 
    throw new ArgumentNullException(nameof(text)); 

foreach (var c in text) 
{ 
    // ... 
} 

, 우리는 몇 년에 널 병합 + 던져 예외 사용량을 볼 수 있으며 새로운 표준 :

+3

그런 식으로는 좋지 않을 수도 있습니다. 원래 코드는 스레드로부터 안전 할 수도 있고 그렇지 않을 수도 있지만 버전은 아닙니다. 왜 이것이 더 낫다고 말 할 수 있는지 설명해 주시겠습니까? – Enigmativity

+3

이전 단락에 따르면, 나는 "코드 가독성 및 흐름"측면에서 더 잘한다고 말했습니다. 값이 처음이나 메소드에서 null인지 확인하고'ArgumentNullException'을 던지는 것은 ** 일반적인 좋은 습관입니다 **. 바로 모든 .NET 클래스, 타사 클래스 및 모든 훌륭한 개발자가하는 일입니다. 모두가 원하는 방식으로 코드 연산자와 기능을 사용하기 시작하면 곧 다른 사람들의 코드를 더 이상 이해하지 않게 될 것입니다. 짧은 코드! = 더 좋습니다. –

+0

스레드 안전성에 대해 말하자면,'text '는 함수에 전달되는 인수라고 가정했습니다. 올바른 경우이 코드는 항상 ** 스레드 안전성을 갖습니다. 클래스 멤버가 다른 것으로부터 수정 될 수 있다면 스레드 안전성을 제공 할 수있는 많은 다른 기법, 접근법 및 기능이 있습니다. 새로운 Exception을 던지기 위해 null-coalescing 연산자를 사용하는 것은 분명히 그 중 하나가 아닙니다. –