2010-03-12 2 views
10

LINQ 시퀀스를 처리하는 동안 자주 foreach 루프를 피하면서 void를 반환하는 메서드에 각 항목을 보내려고합니다. 그러나, 나는 이것을하는 우아한 방법을 발견하지 못했습니다. 당신이 볼 수 있듯이, 난 그냥 true를 돌려 람다 함수를 작성, 나는 선택 방법은 내가 그냥 무시하는거야 booleans-의 순서를 반환 실현void를 반환하는 메서드에 LINQ 시퀀스의 항목 보내기

private StreamWriter _sw; 
    private void streamToFile(List<ErrorEntry> errors) 
    { 
     if (_sw == null) 
     { 
      _sw = new StreamWriter(Path.Combine 
            (Path.GetDirectoryName(_targetDatabasePath), "errors.txt")); 
     } 

     Func<ErrorEntry, bool> writeSelector = 
      (e) => { _sw.WriteLine(getTabDelimititedLine(e)); return true; }; 

     errors.Select(writeSelector); 

     _sw.Flush(); 
    } 

: 오늘, 나는 다음과 같은 코드를 작성 순서. 그러나, 이것은 조금 노작하고 정크 같다. 이 일을하는 우아한 방법이 있습니까? 아니면 LINQ를 잘못 적용하고 있습니까?

감사합니다.

답변

13

우선 현재 코드가 작동하지 않습니다.
Select 및 대부분의 다른 LINQ 메서드는 지연된 실행을 사용합니다. 즉, 결과를 열거 할 때까지 실제로 아무 것도 수행하지 않습니다.

일반적으로 LINQ 쿼리에서 부작용이있는 람다를 사용하지 마십시오.

질문에 대답하려면 foreach 루프를 사용해야합니다.

ForEach 확장 방법을 찾고 있습니다. Eric Lippert explains why Microsoft didn't write one. 당신이 정말로 원하는 경우

, 당신은 하나를 직접 작성할 수 있습니다

public static void ForEach<T>(this IEnumerable<T> sequence, Action<T> action) { 
    if (sequence == null) throw new ArgumentNullException("sequence"); 
    if (action == null) throw new ArgumentNullException("action"); 
    foreach(T item in sequence) 
     action(item); 
} 

//Return false to stop the loop 
public static void ForEach<T>(this IEnumerable<T> sequence, Func<T, bool> action) { 
    if (sequence == null) throw new ArgumentNullException("sequence"); 
    if (action == null) throw new ArgumentNullException("action"); 

    foreach(T item in sequence) 
     if (!action(item)) 
      return; 
} 
+0

답변 해 주셔서 감사합니다. 몇 가지 질문이 있습니다. 어떤 미친 이유로 Select() 메서드가 반환하는 부울 시퀀스에 대해 Count() 메서드를 호출했습니다. 이렇게하면 시퀀스가 ​​열거되고 코드가 제대로 작동합니다. 내 질문은 다음과 같습니다 : 왜 LINQ 쿼리에서 부작용이있는 람다를 사용하지 않아야합니까? [편집 : 링크 주셔서 감사합니다! 나는 그것을 검사 할 것이다.] –

+0

; 'Count()'를 호출하면 시퀀스가 ​​강제로 열거됩니다. – SLaks

+1

람다를 여러 번 실행할 수 있으므로 부작용을 LINQ와 혼합해서는 안됩니다. 람다가 실행되는 횟수를 정확히 아는 것은 매우 어려울 수 있습니다. 람다는 멱등수가되어야합니다. – SLaks

4

일반적인 합의는 반복과 반복에 대한 기존의 반복적 인 방법을 사용하는 동안 LINQ는 ... 쿼리 및 선택을위한 것입니다.

이 말은 싫지만 linq 쿼리를 실행하고 결과 IEnumerable을 반복하기 때문에 전통적인 foreach 루프를 사용하게됩니다. 코드 가독성에 도움이되며 LINQ는 중독성이 있음을 인정합니다. Lambdas와 지연된 실행을 사용하여 모든 작업을 수행하려고하지만 루핑은 기존 C# 루핑 메서드에 맡겨야합니다. 이것은 부작용에 확실히 도움이 될 것입니다.

관련 문제