2012-07-03 5 views
1

다음 코드가 있습니다.컬렉션 변경을 반복하는 방법

private void LoopThroughDependsIssues(JIRAOperations jiraOps, string jiraURL, string token, string username, string password, string projectKey, string exportTargetPath, string branch, SVNOperations svnOps, string svnExePath, string changesetDBFile, DependencyManager mgr) 
     { 
      var tempVar = mgr.Dependencies; 
      foreach (var item in tempVar) 
      { 
       if (item.depends.Length > 0) 
       { 
        var templist = item.depends; 
        var listissues1 = templist.Split(','); 
        for (var i = 0; i < listissues1.Length-1; i++) 
        { 
         var newissue1 = new string[] { listissues1[i].ToString() }; 
         newissue1.getChangeSet(jiraOps, jiraURL, token, username, password, projectKey, exportTargetPath, branch, svnOps, svnExePath, changesetDBFile, mgr); 
        } 
        //throw new Exception("Dependencies found"); 
       } 
      } 
     } 

여기에서 나는 mgr.Dependencis 컬렉션을 반복하고 있습니다. 이 값은 newissue1.getChangeSet(jiraOps, jiraURL, token, username, password, projectKey, exportTargetPath, branch, svnOps, svnExePath, changesetDBFile, mgr); 에서 변경됩니다. 따라서이 메소드를 호출 할 때마다 콜렉션 값이 증가하고 있습니다. 하지만 처음에는 잘 작동합니다. 그러나 두 번째로 iterating 동안 그것은 예외를주고있다

컬렉션이 수정되었습니다; 열거 연산이 실행되지 않을 수 있습니다.

이 예외는 컬렉션을 변경하기위한 것입니다. 이 상황을 어떻게 처리할까요?

내 클래스 정의는 다음과 같습니다.

public class Dependency 
    { 
     public string issueID { get; set; } 
     public string jirastatus { get; set; } 
     public int dependencyFound { get; set; } 
     public string depends { get; set; } 
     public string linked_issues { get; set; } 
     } 

     public class DependencyManager 
     { 
      public List<Dependency> Dependencies { get; private set; } 
      public DependencyManager() 
      { 
       this.Dependencies = new List<Dependency>(); 

      } 
} 
+0

기본 컬렉션에 대한 변경 사항을 검사하고 발견 할 수있는 객체에 반복자를 래핑 할 수 있습니다. 그러나 그것은 가치가있는 것보다 더 큰 문제입니다. 귀찮아하지 않고 반복 할 때 컬렉션을 수정하지 않는 것이 좋습니다. –

+0

@ Jeff.하지만 여기에 새 값을 추가해야합니다. 새 값을 추가하려면 루프를 다시 실행해야합니다. – Searcher

+0

한 번에 너무 많이하려고하는 것 같습니다. 이를 ID의 간단한 문자열 목록에 종속성을 추출하는 함수와 ID 목록이있는 항목의 목록을로드하는 다른 함수로 분리하는 것을 고려하십시오. – overslacked

답변

5

당신은 Dependencies 수집에 인덱스 열거하는 Enumerator가 생성되지 않을 경우 당신이 할 수있는 컬렉션이 수정으로 통해 루프. 이 방법은 새 항목이 목록 끝에 추가되지 않거나 항목이 제거되는 경우 쉽게 두통을 유발할 수 있습니다.

for(int i = 0; i < mgr.Dependencies.Count; i++) 
{ 
    var item = mgr.Dependecies[i]; 
    if (item.depends.Length > 0) 
    { 
     // code unchanged 
    } 
} 

안전한 방법은 Queue를 사용하고 처리 할 mgr.Dependencies에서 초기 항목 다음 Enqueue 추가 항목을 채울 것입니다.

var toBeProcessed = new Queue<Dependency>(mgr.Dependencies); 
while(toBeProcessed.Count > 0) 
{ 
    var item = toBeProcessed.Dequeue(); 

    // loop 

    // if a new dependency gets added that needs processing, just add it to the queue. 
    toBeProcessed.Enqueue(newissue1); 

} 
+0

@ 마이크 .. 감사합니다. 마이크. 하지만 내 코드로 시도 할 때 혼란 스럽다. 내 코드에 이것을 적용 해 주실 수 있나요 ..! – Searcher

+0

@YSSS 첫 번째 예를 명확히했습니다. 사실, 두 번째 예제는 처리 할 새 Dependency 객체에 대한 액세스 권한이 없으면 실행할 수 없습니다. 나는 충분히 자세히 읽지 않았고'newissue1'은'종속성'유형이라고 생각했습니다. –

+0

아니요 .. newissue1은 문자열 [] 유형이 아닙니다. newissues1을 사용하여 확장 메소드를 호출합니다. 그게 다야. – Searcher

2

당신이 원하는 것은 그 변경 사항에 대한 걱정없이, 시작 부분으로 컬렉션을 사용하는 단지의 경우, 당신은 단지 컬렉션의 스냅 샷을 수행 할 수 있습니다

var tempVar = mgr.Dependencies.ToList(); //This will create a new list with the same items 
foreach (var item in tempVar) { 
    ... 
} 
-2

당신은 반복 할 수 있습니다 foreach를 사용하지 않고 일반 루프를 사용하는 경우. 마지막에 수정 된 콜렉션에 행을 추가하는 경우 최소한의 변경만으로 작동합니다.

 var tempVar = mgr.Dependencies; 
     var cnt = tempvar.Count(); // Only iterate items available when we start 

     for (int i = 0; i < cnt; i++) 
     { 
      var item = tempVar[i]; 
+1

중간에 삽입하는 항목을 제거하여 모음을 수정하면 어떨까요? 이것은 좋은 해결책이 아닙니다. – ivowiblo

+0

중간에 제거하거나 삽입하면 좋은 해결책이 아닙니다. 끝 부분에 행만 추가하면됩니다. 어떤 경우에는 완벽하게 작동합니다. 따라서 코드에 따라 코드는 영향이나 변경이 거의없는 솔루션 일 수 있습니다. 이 점을 반영하기 위해 답을 추가 할 것입니다. – IvoTops

+0

하지만 "시작할 때만 항목을 반복 할 수 있습니다."라고 말하면 그것이 사실이 아닙니다. – ivowiblo