[C# 강좌 - 73] default 키워드 (GetType로(Generic 타입으로) 초기 값을 얻는 방법)


Study/C#  2019. 7. 11. 09:00

안녕하세요. 명월입니다.


이 글은 C#에서 default 키워드(default 키워드에서 GetType로(Generic 타입으로) 초기 값을 얻는 방법)에 대한 설명입니다.


제가 default 키워드 설명에 관한 글을 작성했던 걸로 기억하는데 오늘 보니 default 키워드에 대한 설명이 없네요. 좀 순서에는 안 맞지만 작성하겠습니다.

C#에서 사용하는 참조 형식은 reference 참조 방식과 valuable 참조 방식이 있습니다. 더 쉽게 이야기 하면 클래스 방식이냐 구조체 방식이냐의 차이입니다.


링크 - [C# 강좌 - 10] 클래스

링크 - [C# 강좌 - 12] 구조체 (struct)


클래스의 방식의 경우는 new로 할당을 하지 않으면 null로서 메모리에 할당이 되지 않는 식의 표현이 됩니다. 그러나 구조체는 new를 사용하지 않아도 기본 값이 설정이 됩니다.

struct Node
{
  // int형인데 값을 넣지 않았다.
  private int data;
  public void Print()
  {
    Console.WriteLine(data);
  }
}
class Program
{
  // 구조체인데 new로 할당하지 않았다.
  private Node node;

  static void Main(string[] args)
  {
    // Program 클래스를 할당.
    var p = new Program();
    // node는 null이 아니고 Node안의 data도 null이 아니다. 클래스가 아니기 때문에 기본값이 설정되기 때문이다.
    p.node.Print();

    Console.WriteLine("Press any key...");
    Console.ReadKey();
  }
}

그렇다면 클래스의 경우는 할당이 되었는지 안 되었는지를 null로 체크를 하는데 구조체의 경우는 어떻게 확일을 할 수 있을까?

그래서 있는 것이 default 키워드 입니다.

위 예제는 구조체에 null 비교를 하면 컴파일 에러가 발생하는 것을 알 수 있습니다.

struct Node
{
  private int data;
  public void Print()
  {
    Console.WriteLine(data);
  }
}
class Program
{
  private Node node;

  static void Main(string[] args)
  {
    // int의 기본값 = 0
    Console.WriteLine(default(int));
    var p = new Program();
    // node 값이 Node 구조체의 기본값이면 default data를 출력하라
    if (default(Node).Equals(p.node))
    {
      Console.WriteLine("default data");
    }

    Console.WriteLine("Press any key...");
    Console.ReadKey();
  }
}

구조체의 경우는 null이 없기 때문에 default 키워드를 사용해서 default(데이터 타입)을 사용하면 초기화 값이 나와 비교가 가능합니다.


그럼 구조체와 클래스가 혼재된 변수(Object, dynamic)의 경우는 어떻게 확인을 할 수 있을까?

class Program
{
  int a;
  String b;

  static void Main(string[] args)
  {
    var p = new Program();
    List<dynamic> list = new List<dynamic>();
    // 초기화가 되지 않은 int와 String을 넣었다.
    list.Add(p.a);
    list.Add(p.b);
    
    foreach(var item in list)
    {
      // String의 경우는 클래스이기 때문에 null로 인식을 해서 true가 되지만 int형은 null이 없기 때문에 false가 된다.
      if(item == null)
      {
        Console.WriteLine("Null");
      }
    }

    Console.WriteLine("Press any key...");
    Console.ReadKey();
  }
}

주석 내용처럼 int는 null이 없기 때문에 true가 되지 않습니다. 그럼 default(int)형을 사용하면 되는데 그럴 경우 int형은 역시 비교가 되겠지만 byte, short, double 등을 어떻게 처리를 할까요?

이 때는 제네릭을 사용하면 됩니다.

class Program
{
  int a;
  String b;

  static void Main(string[] args)
  {
    var p = new Program();
    List<dynamic> list = new List<dynamic>();
    list.Add(p.a);
    list.Add(p.b);
    
    foreach(var item in list)
    {
      // default에는 정확한 데이터 타입을 넣어야 하기 때문에 default(item.GetType())은 에러가 발생합니다.
      // 제네릭을 사용하면 제네릭이 자동으로 데이터 타입을 맞추어 주기 때문에 GetDefaultData<int>(item)의 값으로 결국 default(int) 값을 얻을 수 있습니다.
      if(item == null || item == GetDefaultData(item))
      {
        Console.WriteLine("Null");
      }
    }

    Console.WriteLine("Press any key...");
    Console.ReadKey();
  }
  // 제네릭을 이용해서 구조체의 default값을 취득한다.
  static T GetDefaultData<T>(T data)
  {
    return default(T);
  }
}

여기까지 default 키워드(default 키워드에서 GetType로(Generic 타입으로) 초기 값을 얻는 방법)에 대한 설명이었습니다.


궁금한 점이나 잘못된 점이 있으면 댓글 부탁드립니다.