여느때와 같이 개발하던 도중, 심심해서 어떤 자료형들이 있나 찾아보던 도중 ArgIterator 이란 구조체가 눈에 띄었습니다.

프로그래밍을 많이 해왔지만, 항상 사용하던 자료형이나 키워드 외에 문서화되지 않은 자료형이나 키워드, 사용하지 않았던 것들은 찾아보지 않은 저로썬 이게 뭔지 이름으로만 유추할 뿐이지 정확한 사용 방법을 알 수가 없었습니다만, MSDN 페이지를 찾아보던 도중 이런 문서를 찾았습니다.


CA2230: 가변 인수로 params를 사용하십시오.


이 문서의 예제 코드를 보시면 아시겠지만, C/C++의 va_list 와 같은 기능을 하는 자료형인 것을 알게 되었습니다.

그리고, __arglist 라는 키워드를 사용하여 값을 받는 것도 알게 되었구요!


위의 페이지에 있는 예제 코드를 약간 변형하여 이런식으로 코딩을 해봤습니다.

(변수 이름이나 자료형을 지정하지 않고 __arglist 를 매개변수 자체로 사용합니다)

using System;
namespace TestApp {
    public class TestApp {
        public static void Main(string[] args) {
            FunWithArgList();
            Console.ReadKey(true);
        }
        private static void FunWithArgList() {
            FunWithArgListBack(__arglist(123"문자열"'c'"__arglist"null));
        }
        private static void FunWithArgListBack(__arglist) {
            ArgIterator ai = new ArgIterator(__arglist);
            Int32 ArgCount = ai.GetRemainingCount();
            for ( Int32 i = 0; i < ArgCount; i++ ) {
                TypedReference tr = ai.GetNextArg();
                Console.WriteLine("Arg #{0}: {1,-20} ({2})", i, TypedReference.ToObject(tr), __reftype(tr));
            }
        }
    }
}


위 코드의 결과 값은 이렇게 나옵니다.


위 결과에서 전달된 총 6개의 매개 변수의 값과 형식이 나오는 것을 확인할 수 있습니다.

그리고, ArgIterator 구조체는 RuntimeArgumentHandle 형식을 받아서 초기화하고 있는데, __arglist 키워드는 RuntimeArgumentHandle 형식으로 바뀌는 것 같습니다.


또 여기서 사용된 __reftype 이란 키워드가 있는데, 이 키워드는 TypedReference 구조체의 자료형을 가져오는 키워드입니다.

이 키워드의 설명을 보면, 변수의 원본 형식을 가져온다고 되어있네요. 그래서 매개 변수의 형식이 나오는듯 합니다.


이 키워드는 컴파일러를 만들 때 유용하다고 써져있네요..

하지만, CLS(공용 언어 사양)을 따르지 않기 때문에 다른 언어간의 호환은 힘들 것이라 생각합니다.

CLS를 따르기 위해선 __arglist 대신 params 를 사용하라고 합니다.

params 키워드를 이용해서도 __arglist 키워드를 대신할 수 있습니다.

그래서, 한번 __arglist 를 params 키워드로 대체하는 코드를 작성해 보았습니다.

using System;
namespace TestApp {
    public class TestApp {
        public static void Main(string[] args) {
            FunWithParams();
            Console.ReadKey(true);
        }
        private static void FunWithParams() {
            object[] args = {123"문자열"'c'"__arglist"null};
            FunWithParamsBack(args);
        }
        private static void FunWithParamsBack(params object[] args) {
            for ( Int32 i = 0; i < args.Length; i++ ) {
                if ( args[i] == null )
                    Console.WriteLine("Params Arg #{0}: {1,-20} ({2})", i, "null"typeof(object));
                else
                    Console.WriteLine("Params Arg #{0}: {1,-20} ({2})", i, args[i], args[i].GetType());
            }
        }
    }
}


이런식으로 CLS를 따르는 코드를 작성할 수 있습니다.

그리고 이 코드의 결과는 아래 그림과 같습니다.

위의 결과를 보시면 __arglist 키워드를 사용한 것이나 params 키워드를 사용한 것이나 결과는 같은 것을 확인하실 수 있습니다. 그리고, __arglist 의 경우 null 값을 전달해도 자료형이나 값을 (null) 로 표시할 수 있었지만, params 키워드를 사용한 경우에는 값에 대해서 null 값의 여부를 체크해주거나 try ~ catch 로 예외 처리를 해줘야 프로그램이 예외를 발생시켜 멈추는 현상을 방지할 수 있습니다.


결론은, 이런 키워드, 구조체도 있구나 싶습니다 ㅋㅋ;

__reftype 이란 키워드 오늘 처음봤습니다. 비주얼 베이직의 VarPtr 이런 메서드처럼 문서화되지 않은 키워드가 꽤 되나봅니다.

문서화 되지 않은 키워드는 찾는 즉시 계속 설명을 해보도록 하겠습니다 ㅋ.ㅋ


긴 글 읽어주셔서 감사합니다. (--)(__)


참고 문서:

http://www.nullskull.com/articles/20030114.asp

http://msdn.microsoft.com/ko-kr/library/ms182366.aspx

+ Recent posts