2014-09-19 2 views
0

나는 프로그래밍과 프로그래밍에있어 C#으로 멍청하다. (나는 기본적인 자바를 배웠다.) 나는 Unity3D에서 C#을 함께 놀러하려고, 나는 질문이있다 : 그것은 ArrayList에있는 모든 항목을 제거하는 루프 대신 foreach는 반복 사용하는 것이 더C# : foreach 또는 for 루프를 사용하여 ArrayList에서 항목을 제거 하시겠습니까?

인가를?

모두 나를 위해 작동하는 것 같습니다. Foreach는 코딩을 약간 덜 생성하지만 discussions onthe Internet은 for 루프를 선호하는 것 같습니다. 어느 쪽이 더 낫고 왜?

에 대한 루프 버전 :

public void RemoveUnitFromList(GameObject Unit) { 
    if (SelectedUnitList.Count > 0) { 
     for (int i = 0; i < SelectedUnitList.Count; i++) { 
      GameObject ArrayListUnit = SelectedUnitList[i] as GameObject; 
      if (ArrayListUnit == Unit) { 
       SelectedUnitList.RemoveAt(i); 
       // some other codes 
      } 
     } 
    } 
} 

의 foreach 버전 :

public void RemoveUnitFromList(GameObject Unit) { 
    if (SelectedUnitList.Count > 0) { 
     foreach (GameObject ArrayListUnit in new ArrayList(SelectedUnitList)) { 
      if (ArrayListUnit == Unit) { 
       SelectedUnitList.Remove(ArrayListUnit); 
       // some other codes 
      } 
     } 
    } 
} 

편집 : 코드 조각의 어느 쪽이 위의 나를 위해 잘 작동합니다. 나는이 둘의 차이점 만 연구하고 싶다. in new ArrayList(SelectedUnitList)in SelectedUnitList에 변경 그러나 는 작동하지 않았다 :

public void RemoveUnitFromList(GameObject Unit) { 
    if (SelectedUnitList.Count > 0) { 
     foreach (GameObject ArrayListUnit in SelectedUnitList) { 
      if (ArrayListUnit == Unit) { 
       SelectedUnitList.Remove(ArrayListUnit); 
       // some other codes 
      } 
     } 
    } 
} 

Edit2가를 : 은 위의 코드는 다음과 같은 오류를 생산할 수 :

InvalidOperationException: List has changed. 
System.Collections.ArrayList+SimpleEnumerator.MoveNext() (at /Users/builduser/buildslave/mono-runtime-and-classlibs/build/mcs/class/corlib/System.Collections/ArrayList.cs:141) 
Mouse3.RemoveUnitFromList (UnityEngine.GameObject Unit) (at Assets/Scripts/Mouse3.cs:216) 
Mouse3.Update() (at Assets/Scripts/Mouse3.cs:85) 

이 좀 더 설명하겠습니다. 이 메소드는 게임에서 동적으로 기능합니다. SelectedUnitList은 RTS 게임에서 선택된 유닛을 수집하는 데 사용되는 ArrayList입니다. 이 메서드는 ArrayList에서 선택 취소 된 유닛을 제거하므로 Unit은 0, 1 이상일 수 있습니다.

편집 3 (마지막) : 제공된 모든 정보를 제공해 주셔서 감사합니다. 나는 코멘트에서 @Seminda가 나의 질문에 대답했다고 생각한다. foreach Loop에 MSDN 문서에서

+0

힌트 : :이 경우

은 당신의 코드는 아래로 비등 그것은'new' 키워드에 관한 것입니다. Btw, if 문은 두 경우 모두 쓸모가 없습니다. – Mephy

+0

실제로 코드는 [온라인 튜토리얼] (https://www.youtube.com/watch?v=vSshzqMpv20&index=9&list=PLcGWkWha2wFd5Azr14ZJjvfnAmUKM_3E7)에서 복사/수정되었으며 'Unit' 아무것도 가지고 있지 않습니까? 음 ... 힌트를 주셔서 감사합니다. 'new'키워드가 없으면 'foreach'가 작동하지 않습니다. 나는 내가 이해하지 않는 것을 생각한다. 스레딩과 관련이 있습니까? –

+0

이 설명을 확인하고 코드에 적용하여 어떤 코드가 좋은지 확인하십시오. http://www.john.edu/pub/detnetperls.com/for-foreach – Seminda

답변

2

: 코드에

The foreach statement is used to iterate through the collection to get the information that you want, but can not be used to add or remove items from the source collection to avoid unpredictable side effects. If you need to add or remove items from the source collection, use a for loop.

참고, 참고 것은 다음 :

ArrayList에 대한 세부 정보를 참조하십시오. 일반적으로 List을 사용하는 것이 좋습니다. 목록은 복싱이나 언 박싱을 피할뿐만 아니라 버그가 발생하기 쉬운 명확한 코드로 이어집니다.

UPDATE : 새로운 ArrayList를 초기화하기 때문에

foreach (질문 2 번째 조각은) 작동합니다.

foreach (GameObject ArrayListUnit in new ArrayList(SelectedUnitList)) 

중복 ArrayList를 초기화하고 반복에만 사용했습니다. 그러나 foreach 루프 내에서 ArrayList에서 제거하면 실제 ArrayList 즉 SelectedUnitList에서 가져옵니다.

Conculsion :

사용 for loop 중복과의 ArrayList에서 제거를 방지 할 수 있습니다.

+0

컬렉션이 동일하지 않습니다. – Mephy

+0

여기에 컬렉션을 언급하지 않습니다. 방금 foreach와 for 루프의 차이점을 언급했습니다. – Hassan

+0

'foreach (새 ArrayList (SelectedUnitList)의 GameObject ArrayListUnit) '가 작동했지만'foreach (SelectedUnitList의 GameObject ArrayListUnit)'가 예외를 던졌습니다. –

0

동일합니다. 대부분의 경우 나는 적은 코드를 생성하기 때문에 foreach를 사용한다. 현재 컬렉션에 대한 일부 항목을 삭제/추가하려는 경우에만 사용합니다.

당신은 당신이 정확하게하려면 약간의 코드를 수정할 수 있습니다

이 두 문제가 될거야
public void RemoveUnitFromList(GameObject Unit) 
{ 
    if (SelectedUnitList.Count == 0) 
     return; 

     foreach (GameObject ArrayListUnit in new ArrayList(SelectedUnitList)) 
     { 
      if (ArrayListUnit != Unit) 
       continue; 

       SelectedUnitList.Remove(ArrayListUnit); 
       DeactivateProjectorOfObject(ArrayListUnit); 


     } 
    } 
} 
1

. 배열의 전체 복사본이 만들어 졌는지 또는 얕은 복사본이 "컬렉션이 수정되었지만 열거 연산이 실행되지 않을 수 있습니다. 목록 항목을 제거하면"과 같이 foreach를 사용하는 방식을 유지할 것입니다. 나는이 경우 foreach가 깊은 복사본이 생성 될 때 작동 할 것이라고 생각한다. 그러나 큰 목록의 경우 이는 비효율적 일 수 있습니다. 전체 배열의 복사본을 만들지 않고도 배열에서 항목을 제거 할 수 있습니다.

유닛과 일치하는 SelectedUnitList에 단 하나의 아이템이 있다고 생각합니까? 그렇지 않으면 for 루프를 사용하는 코드의 첫 번째 비트가 실패합니다. 대신 뒤로 다음 항목이 이전 반복에있는 항목의 제거에 의해 영향을받지 않습니다에 반복하도록 항목을 제거 루프 ...

public void RemoveUnitFromList(GameObject Unit) { 
    if (SelectedUnitList.Count > 0) { 
     for (int i = SelectedUnitList.Count -1; i >= 0; i--) { 
      GameObject ArrayListUnit = SelectedUnitList[i] as GameObject; 
      if (ArrayListUnit == Unit) { 
       SelectedUnitList.RemoveAt(i); 
       DeactivateProjectorOfObject(ArrayListUnit); 
      } 
     } 
    } 
} 

이 코드를 원하는 것입니다. 하나 개의 항목 만 일치하는 게임 장치가 가정

....

GameObject arrayListUnit = SelectedUnitList.SingleOrDefault(u => u == unit); 
DeactivateProjectorOfObject(arrayListUnit); 
SelectedUnitList.Remove(unit); 

이 또한 내가 유니티 개발자들과 진행하지만 당신이 정말로 코딩 표준에 대한 몇 가지 지침을 읽기 시작해야하는 건지 모르겠어요. 내가 본 코딩 표준에는 자본으로 시작하는 변수가 없습니다.

http://m.friendfeed-media.com/fc2fd89c8be6ace85f7bacedb14181d76ba6c8be

+0

다른 주석에서 언급했듯이 코드는 [온라인 자습서] (https://www.youtube.com/watch?v=vSshzqMpv20&index=9&list=PLcGWkWha2wFd5Azr14ZJjvfnAmUKM_3E7)에서 복사/수정되었으며 변수는 'public static'입니다. 가이드 라인을 가져 주셔서 감사합니다. 나는 시간이있을 때 그것을 읽을 것이다. –

+0

"foreach를 사용할 수 없습니다"라는 문구는 * 질문에 게시 된 코드에는 적용되지 않습니다 (반복 전에 소스 사본을 만듭니다). 당신은 조금 대답을 조정하고 싶을 수도 있습니다 ... –

+0

@AlexeiLevenkov correct – Mick

1

나는 당신이 당신이 그것을 제거하기로 결정 각 개체에 대한 처리를 수행 할 계획 나의 선호하는 방법이 최종 처리를하는 동안 제거 할 항목의 목록을 구축하는 것입니다, 다음 별도의 루프, 항목을 제거하십시오. 또한 입력 된 목록 (System.Collections.Generic.List <>)을 사용하십시오. 유형이 지정되지 않은 목록은 실수로 목록에 잘못된 유형의 항목이 추가되면 런타임에 문제를 묻는 것입니다. 형식화 된 목록은 컴파일 타임 보호 기능을 제공하여 해당 문제를 제거합니다.

나는 물어야한다 - 당신이 제거 될 특정 게임 객체를 전달한다면, 왜 모든 것을 루프 할 필요가 있는가? ArrayList.Remove는 객체 매개 변수를 취합니다. 처음에는 선택한 유닛 목록에 동일한 게임 객체를 두 번 가져서는 안됩니다. 실제로 중복을 방지하기 위해 SelectedUnitList를 작성하는 코드에 몇 가지 검사를 추가해야합니다. 또한 .. 당신이 중복 발생하는 경우 DeactivateProjectorOfObject 같은 개체에 두 번 전화를 안전합니까 ??

 

    public void RemoveUnitFromList(GameObject Unit) { 
     DeactivateProjectorOfObject(unit); 
     SelectedUnitList.Remove(unit); 
    } 

관련 문제