[C#] 6.2.2 is 연산자와 as 연산자를 이용한 하향 캐스팅

이처럼 기반 형식의 변수로 파생된 개체를 참조할 수 있다는 특징은 사용의 편의성이 제공합니다. 하지만 프로그램에서 파생 형식에만 캡슐화된 멤버에 접근하여 사용해야 할 때도 있습니다. 이 때 is 연산자와 as 연산자를 사용하면 파생 개체를 참조할 수 있습니다.

▶ 용어: 상향 캐스팅 , 하향 캐스팅

기반 형식의 변수로 파생된 형식 개체를 참조하는 것을 상향 캐스팅이라 하고 기반 형식의 변수에 참조하는 개체를 파생 형식 변수로 참조하는 것을 하향 캐스팅이라고 합니다.
C#에서는 기반 형식의 변수로 파생된 형식 개체를 참조하는 상향 캐스팅은 묵시적으로 사용할 수 있지만, 기반 형식의 변수가 참조하는 파생 개체를 파생된 형식 변수로 하향 캐스팅하는 것은 묵시적으로 사용할 수 없고 as 연산자나 is 연산자를 사용해야 합니다.

as 연산자는 이항 연산자로 좌항에 개체를 참조하는 변수가 오고 우항에 참조하려는 형식을 명시하여 사용합니다. 만약, 해당 변수가 참조하는 개체가 우항에 오는 형식이 바르다면 해당 형식의 개체 참조를 반환하고 그렇지 않으면 null을 반환합니다. 이처럼 as 연산은 참조 형식에 사용할 수 있습니다.

▶ as 연산으로 파생 형식 개체 참조

Stu stu = man as Stu; //파생된 형식 개체 참조
if (stu != null) //man이 Stu개체일 때
{
    stu.Study();
}
else
{
    Console.WriteLine("Stu 형식 개체가 아닙니다. ");
}

is 연산자는 이항 연산자로 좌항에 변수가 오고 우항에 형식 명을 명시하면 해당 변수가 해당 형식으로 호환할 수 있는지를 반환합니다. is 연산은 as 연산과 달리 값 형식에서도 사용할 수 있으며 형 변환하기 전에 호환 여부를 확인하기 위해 사용됩니다.

▶ is 연산으로 형 변환 호환 여부 확인

Man man = new Stu();
if (man is Stu) //man이 Stu개체일 때
{
    Stu stu = (Stu)man; 
    stu.Study();
}
object obj = 3;
if (obj is int) //obj가 int 형식일 때
{
    int i = (int)obj;
    Console.WriteLine(i.ToString());
}

특히 컬렉션을 통해 요소 개체가 특정 형식일 때 수행할 때 하향 캐스팅을 사용합니다.

▶ 컬렉션 요소  개체 참조 위해 as 연산자 이용

class Man
{
    internal string Name
    {
        get;
        private set;
    }
    internal Man(string name)
    {
        Name = name;
    }
    internal void Eat()
    {
        Console.WriteLine("{0} 밥을 먹다.",Name);
    }
}
class Stu : Man //기반 형식 Man에서 파생
{
    internal Stu(string name): base(name)
    {
    }
    internal void Study()
    {
        Console.WriteLine("{0} 공부하다.",Name);
    }
}
class Program
{
    static void Main()
    {
        Man[] people = new Man[2];
        people[0] = new Stu("홍길동"); //기반 형식으로 파생 개체 참조
        people[1] = new Man("강감찬");
        Stu stu = null;
        foreach (Man man in people)
        {
            man.Eat();
            stu = man as Stu; //as 연산으로 파생 개체 참조
            if (stu != null) //참조한 개체가 Stu 형식 개체일 때
            {
                stu.Study();
            }
        }
    }
}