C#

C# Value Type : 값 형식

_dev_mu ㅣ 2023. 1. 12. 22:42

값 형식 및 참조 형식은 C# 형식의 두 가지 주요 범주입니다.
값 형식의 변수에는 형식의 인스턴스가 포함되어 있습니다.
이는 형식 인스턴스에 대한 참조를 포함하는 참조 형식의 변수와 다릅니다.
기본적으로 변수 값은 할당 시에, 인수를 메서드에 전달할 때, 그리고 메서드 결과를 반환할 때 복사됩니다.
값 형식 변수의 경우 해당 형식 인스턴스가 복사됩니다.
using System;

public struct MutablePoint
{
    public int X;
    public int Y;

    public MutablePoint(int x, int y) => (X, Y) = (x, y);

    public override string ToString() => $"({X}, {Y})";
}

public class Program
{
    public static void Main()
    {
        var p1 = new MutablePoint(1, 2);
        var p2 = p1;
        p2.Y = 200;
        Console.WriteLine($"{nameof(p1)} after {nameof(p2)} is modified: {p1}");
        Console.WriteLine($"{nameof(p2)}: {p2}");

        MutateAndDisplay(p2);
        Console.WriteLine($"{nameof(p2)} after passing to a method: {p2}");
    }

    private static void MutateAndDisplay(MutablePoint p)
    {
        p.X = 100;
        Console.WriteLine($"Point mutated in a method: {p}");
    }
}
// Expected output:
// p1 after p2 is modified: (1, 2)
// p2: (1, 200)
// Point mutated in a method: (100, 200)
// p2 after passing to a method: (1, 200)
앞의 예제와 같이 값 형식 변수에 대한 작업은 변수에 저장된 값 형식의 인스턴스에만 영향을 줍니다.

값 형식이 참조 형식의 데이터 구성원을 포함하는 경우에는 값 형식 인스턴스가 복사될 때 참조 형식의 인스턴스에 대한 참조만 복사됩니다.
복사 및 원래 값 형식 인스턴스는 모두 동일한 참조 형식 인스턴스에 엑세스할 수 있습니다.
using System;
using System.Collections.Generic;

public struct TaggedInteger
{
    public int Number;
    private List<string> tags;

    public TaggedInteger(int n)
    {
        Number = n;
        tags = new List<string>();
    }

    public void AddTag(string tag) => tags.Add(tag);

    public override string ToString() => $"{Number} [{string.Join(", ", tags)}]";
}

public class Program
{
    public static void Main()
    {
        var n1 = new TaggedInteger(0);
        n1.AddTag("A");
        Console.WriteLine(n1);  // output: 0 [A]

        var n2 = n1;
        n2.Number = 7;
        n2.AddTag("B");

        Console.WriteLine(n1);  // output: 0 [A, B]
        Console.WriteLine(n2);  // output: 7 [A, B]
    }
}

 

값 형식 및 형식 제약 조건의 종류

값 형식은 다음 두 가지 중 하나일 수 있습니다.
1. 데이터 및 관련 기능을 캡슐화하는 구조 형식.
2. 명명된 상수 집합으로 정의되고 선택 사항 또는 선택 사항의 조합을 나타내는 열거 형식.

nullable 값 형식은 기본 값 형식 T? T 의 모든 값과 추가 null 값을 나타냅니다.
Null 값 형식인 경우를 제외하고는 값 형식의 변수에 null을 할당할 수 없습니다.

struct 제약 조건을 사용하여 형식 매개 변수가 null을 허용하지 않는 값 형식이라고 지정할 수 있습니다.
구조체 형식과 열거형 형식 모두 struct 제약  조건을 충족합니다.
키본 클래스 제약 조건에서 형식 매개 변수가 열거형 형식임을 지정하는 데 System.Enum을 사용할 수 있습니다. 

 

기본 제공 값 형식

C#은 단순 형식이라고도 하는 다음과 같은 기본 제공 값 형식을 제공합니다.
- 정수 숫자 형식
- 부동 소수점 숫자 형식
- 부울 값을 나타내는 bool
- 유니코드 UTF-16 문자를 나타내는 문자
모든 단순 형식은 구조체 형식이며, 특정 추가 작업을 허용한다는 점에서 다른 구조체 형식과 다릅니다.
- 리터럴을 사용하여 단순 형식의 값을 제공할 수 있습니다. 예를들어 'A'는 char형식의 리터럴이고, 2001은 int 형식의 리터럴입니다.
- const 키워드를 사용하여 단순 형식의 상수를 선언할 수 있습니다. 다른 구조체 형식의 상수는 포함할 수 없습니다.
- 해당 피연산자가 모두 단순 형식의 상수인 상수 식은 컴파일 시간에 계산됩니다.

값 튜플은 값 형식이지만 단순 형식은 아닙니다.
C#에서는 단순 형식이라는 미리 정의된 구조체 형식의 집합을 제공합니다.
단순 형식은 예약어를 통해 식별됩니다.
value_type
    : struct_type
    | enum_type
    ;

struct_type
    : type_name
    | simple_type
    | nullable_type
    ;

simple_type
    : numeric_type
    | 'bool'
    ;

numeric_type
    : integral_type
    | floating_point_type
    | 'decimal'
    ;

integral_type
    : 'sbyte'
    | 'byte'
    | 'short'
    | 'ushort'
    | 'int'
    | 'uint'
    | 'long'
    | 'ulong'
    | 'char'
    ;

floating_point_type
    : 'float'
    | 'double'
    ;

nullable_type
    : non_nullable_value_type '?'
    ;

non_nullable_value_type
    : type
    ;

enum_type
    : type_name
    ;
참조 형식은 변수와 달리 null 값 형식의 변수는 값 형식이 nullable 형식인 경우에만 값을 포함할 수 있습니다.
Null을 허용 하지 않는 모든 값 형식에 대해 null 값과 값의 동일한 집합을 나타내는 해당 nullable 값 형식이 있습니다.

 값 형식의 변수에 할당 하면 할당 되는 값의 복사본이 생성됩니다.
이는 참조를 복사하지만 참조로 식별되는 개체가 아닌 참조 형식의 변수에 대한 할당과 다릅니다.