위와 같은 Custom Collection 이 있다고 할때 .Net Framework 2.0에서 COM Interop에서 GetEnumerator()를 호출하여 IEnumVARIANT를 얻고, 안에 담고있는 Object 배열을 얻기위해의 Next(unsigned long celt, VARIANT FAR *rgVar, unsigned long FAR *pCeltFetched ) 메서드를 호출할 경우 Collection 에서 얻은 Count(celt)만큼 pCeltFetched에 리턴되나 rgVar 은 VT_EMPTY형으로 InvalidOperationException (0x80131509 ) 에러를 리턴함.
2.0 SDK 도움말을 보면 다음과 같은 말이 나와 있음
잘못된 인수 이외의 다른 이유로 메서드를 호출할 없는 경우 InvalidOperationException이 사용됩니다. 예를 들어, InvalidOperationException은 다음과 같은 경우에 throw됩니다.
열거자를 만든 후 컬렉션의 개체가 수정되는 경우 MoveNext 메서드에 의해 예외가 throw됩니다.
메서드를 호출하기 전에 리소스 집합이 닫히는 경우 GetString 메서드에 의해 예외가 throw됩니다.
이 형식의 모든 public static(Visual Basic의 경우 Shared) 멤버는 스레드로부터 안전합니다. 인터페이스 멤버는 스레드로부터 안전하지 않습니다.
위의 내용대로 Next 호출시 컬렉션 개체가 수정되고 있는듯.
IEnumerable, IEnumerator 인터페이스를 상속받아 구현해주었으나 효과 없음.
IEnumerable의 메서드 GetEnumerator는 CollectionBase에 구현되어 있다.
CollectionBase와 IEnuerator을 상속받을 경우 GetEnumerator을 통해 ArrayList의 IEnumerator를 받으므로 ArrayList에 구현된 Reset, Current, MoveNext 가 호출되어 SapeCollection에 구현된 Reset, Current, MoveNext 가 무시된다.
자신만의 Custom Collection을 구현하기 위해서는 IEnumerable, IEnumerator를 상속받아 GetEnumerator, Reset, Current, MoveNext를 정교하게 구현하여야 한다.
ShapeCollection의 경우 CollectionBase에서 제공하는 다른 Method들도 요구하므로 CollectionBase를 사용하여야 한다.
결론적으로 Next 호출시 내부적으로 MoveNext가 호출되고 이때 요소가 삭제, 추가등으로 변경되어 InvalidOperation Exception이 발생하는 것으로 생각된다. 2.0에서 왜 요소가 변경될까? 아마 CollectionBase 의 내부 구조가 변경된듯 하다.
2.0의 RegAsm.exe를 사용하여 tlb를 만들었으나 역시 상관없는둣.
1.1 도 되고 2.0, 기타 상위버전에서 확실해 돌아 갈 수 있는 해결책을 찾지못함
2.0 SDK를 사용할 수 있는 개발환경이라면(VS .NET 2005) Generic 사용을 적극 검토하라.! 1.1 이하에서 Custom Collection을 CollectionBase로 구현했다면 1.1 Runtime에서 동작하도록 강제하는 방법밖에 없는듯 하다.