본문 바로가기

프로그래밍/C# 프로그래밍

C# nullable 형식 - 포인터화?



C# 문법을 접하면서 놀라운것중 하나는 바로 nullable 형식이다.



 nullable 형식은 System.Nullable<T> 구조체의 인스턴스이다.





바로 nullable 형식은 내부 값 형식의 올바른 값 범위뿐 아니라 null 값도 나타낼 수 있다


포인터는 아니지만 null 대입 허용을 하겠다는 것이다.


Nullable<Int32> nullInt = null;

Nullable<Int32> nullInt = 100;


이런식으로 기본형 데이터 말고 null값을 대입할 수 있게 해준다.




또한 귀차니즘을 위해 축약형도 제공을 하고 있는데 바로 '?' 라는 키워드이다.


bool? nullBool = null;

bool? nullBool = true;


바로 타입 바로뒤에 ? 를 붙여주면 null 대입이 허용된다.


null허용이 된다면 해당데이터가 값을 가지고 있는지 HasValue() 로 체크를 할 수 있다.




        static void Main(string[] args)

        {

            int? num = null;


   

            if (num.HasValue)

            {

                System.Console.WriteLine("num = " + num.Value);

            }

            else

            {

                System.Console.WriteLine("num = Null");// num은 null이기 때문에 여기에 걸린다.

            }


            

            int y = num.GetValueOrDefault(); // 0으로 셋팅


            // num.Value throws an InvalidOperationException if num.HasValue is false

            try

            {

                y = num.Value; // num은 null이기 때문에 할당에 실패하여 예외처리 된다.

            }

            catch (System.InvalidOperationException e)

            {

                System.Console.WriteLine(e.Message);

            }

        }



몇가지 특성을 더 나열해 본다면,


?? 연산자를 사용하여 null 인지 체크를 하여 기본값을 할당할 수 있다.


int? x = null;


int y = x ?? -1; // x는 null 이기 때문에 -1이 할당



is 연산자로 체크할 수도 있다.


int? i = 5;
    if (i is int) // true


만약에 bool? 타입을 bool로 캐스팅할려면 어떻게 해야할까?


그냥 무턱대고 캐스팅하면 에러가 난다.

bool? b = null;
if (b) // Error CS0266.
{
// b가 불명확하기 때문에 컴파일에러 발생
}

bool? test = null; if (!test.HasValue) // HasValue 로 체크를 한 후 {     test = true; // null이 아닌값으로 초기화를 해줘야 한다 } if ((bool)test) // 캐스팅 한다 {     // 안전하게 캐스팅이 되었음 }

이런식으로 초기화를 한 후, 캐스팅을 해야 한다.


초기화를 해주지 않으면, InvalidOperationException 가 Throw 된다.





Boxing은 어떨까?


nullable 형식을 기반으로 한 개체는 이 개체가 null이 아닌 경우에만 boxing 이 된다.


HasValue 가 false인 경우 boxing하는 대신 개체 참조가 null에 할당


bool? b = null; object obj = b; // obj는 null이 된다




개체가 null 이 아니고, nullable 개체의 기반이 되는 내부 형식이라면 boxing, unboxing 이 된다.


bool? b = false;
int? i = 44;
object bBoxed = b;
object iBoxed = i;// Boxing

bool? b2 = (bool?)bBoxed; int? i2 = (int?)iBoxed; // UnBoxing




GetType으로 원래 기본형을 검출할 수 있다.


int? i = 5;
Type t = i.GetType();
Console.WriteLine(t.FullName); //"System.Int32"



사실 자주쓰는 문법은 아니다.


하지만, 데이터를 선언하고 귀차니즘에 의해 값을 할당하지 않고 사용할때


데이터가 있는지 체크할때 유용하다.



마지막으로 nullable 형식에 대해 정리한다.





* nullable 형식은 null 값을 할당할 수 있는 값 형식 변수를 나타낸다.


* 참조 형식에서는 이미 null 값을 지원하기 때문에 nullable 형식으로 만들 수 없다.


* Nullable<T>.GetValueOrDefault 메서드를 사용하여 할당된 값을 반환하거나 값이 null인 경우 

  내부 형식의 기본값을 반환한다.


* HasValue 및 Value 읽기 전용 속성을 사용하여 Null에 대해 테스트하고 값을 검색할 수 있다.


* HasValue 속성은 변수에 값이 포함되어 있을 경우 true를 반환하고, 변수가 null이면 false를 반환한다.


* 할당된 값이 있으면 Value 속성은 값을 반환한다. 그렇지 않으면 System.InvalidOperationException이 throw된다.


* HasValue의 기본값은 false이며 Value 속성에는 기본값이 없다.


* == and != 연산자를 Nullable 형식으로 사용할 수도 있다.


* ?? 연산자를 사용하여 현재 값이 null인 nullable 형식을 nullable이 아닌 형식에 할당할 때 적용될 기본값을 할당한다.


* 중첩된 nullable 형식은 허용되지 않는다. Nullable<Nullable<int>> n; 과 같은 줄은 컴파일되지 않는다.






https://msdn.microsoft.com/ko-kr/library/b3h38hb0.aspx