coding/c#

C# record? struct? class?

사과키라임파이 2021. 12. 20. 01:35

recorc, struct 불변타입

 

https://www.daveabrock.com/2020/07/06/c-sharp-9-deep-dive-records/

 

C# 9 Deep Dive: Records

In a C# 9 deep dive, we go in depth on records.

www.daveabrock.com

 

 

C# 9에 record라는 class와 유사하고 또 struct와도 유사한 타입이 생겼습니다. 불변개체를 다루기 위한 타입인데, 사실 class또는 struct으로 이와 유사하거나 거의 동일하게 쓸수는 있습니다만, record타입을 추가해서 코딩량을 줄이고 불변개체사용을 유도하며 사실은 함수형 언어의 장점을 차용한 기능이라고 할 수 있겠네요. 간단히 사용해 본 결과 코드량이 줄고 record 으로 만들어진 인스턴스의 모든 요소가 불변성이라는 인식(믿음)이 프로그래밍 하는데 상당히 유용하다는 것을 깨달았습니다. 아래 글은 Record가 무엇인지에 대해 잘 설명한 글입니다.

 
 

C# 구조체는 언제든 초기화되지 않은 값, 임의 구조체 T에 대해 그러니까 default(T)가 존재할 수 있다는 것을 감안하지 않을 수 없는데, 그에 비해 레코드는 언제나 일정하게 초기화되어 있다는 가정을 할 수 있어서 그것도 좋은 것 같습니다. C# 구조체는 이름부터가 결국 C/C++ 스타일 구조체로부터의 연속성을 아주 버리진 못한 느낌이지요. 심지어 기본 생성자를 재정의할 수 조차 없어서 모든 필드가 default 값으로 채워진(필드가 참조 타입이면 null) 초기화가 아예 안 된 상태가 있다는 것을 받아들여야 하는데, 단순히 불변 객체로 만들어서 쓰기에는 제약이 너무 컸습니다.

 

https://forum.dotnetdev.kr/t/c-9-record-struct/113

 

C# 9의 Record와 Struct의 차이점

C# 9에 record라는 class와 유사하고 또 struct와도 유사한 타입이 생겼습니다. 불변개체를 다루기 위한 타입인데, 사실 class또는 struct으로 이와 유사하거나 거의 동일하게 쓸수는 있습니다만, record타

forum.dotnetdev.kr

 

https://www.sysnet.pe.kr/2/0/12392

 

.NET Framework: 959. C# 9.0 - (9) 레코드(Records)

.NET Framework: 959. C# 9.0 - (9) 레코드(Records) [링크 복사], [링크+제목 복사] 조회: 2817 글쓴 사람 정성태 (techsharer at outlook.com) 홈페이지 첨부 파일 부모글 보이기/감추기 C# 9.0 - (9) 레코드(Records) C# 9.0 -

www.sysnet.pe.kr

 

 

C# 9.0: 레코드(record) 타입

C# 9.0 에서 가장 두드러진 변화는 record 타입을 새로 도입한 것이다. 지금까지의 C#/.NET에서는 struct를 사용하는 Value Type(값 타입)과 class를 사용하는 Reference Type(레퍼런스 타입)이 있었는데, C# 9에서 Immutable 값 데이타를 갖는 record 타입을 추가하였다. 새로 도입된 record 타입은 객체 내의 멤버가 변하지 않는 Immutable Reference Type을 만들기 위한 것이다. C# 9에서는 이를 위해 record 라는 새로운 키워드를 도입했으며, class 키워드를 사용해서 클래스를 정의하는 것이 아니라, 이 record라는 키워드를 통해 Immutable Type을 정의하게 된다.

예제

// 예제(1)
public record Person
{
    public string Name { get; }
    public int Age { get; }

    public Person(string name, int age)
        => (Name, Age) = (name, age);
}

class Program
{
    static void Main(string[] args)
    {
        Person p = new Person("Tom", 30);
        string s = p.Name;
    }
}

C# 9.0: init only setter

C# 9.0에서 새롭게 추가된 키워드로 init 이라는 키워드가 있다. init은 속성을 정의할 때 쓰는 set 대신에 사용하는데, set으로 정의된 속성이 흔히 객체 생성 이후에 속성을 변경하는데 사용되는 것이라면, init은 객체가 처음 초기화될 때만 속성을 변경할 수 있다. init 키워드는 해당 속성을 Immutable(불변) 속성으로 만드는 역활을 하게 된다. init이 하나의 속성을 Immutable로 만드는 것이라면, record 타입은 객체 전체를 Immutable로 만드는 것으로 볼 수 있다. record 타입을 정의할 때 위 예제(1)과 같이 생성자를 쓰는 대신, 아래와 같이 init과 객체 초기자(Object Initializer)를 사용할 수 있는데 만약 필드/속성의 수가 많다면, 아래 표현이 더 간결할 수 있다.

예제

// 예제(2)
public record Person
{
    public string Name { get; init; }
    public int Age { get; init; }
}

class Program
{
    static void Main(string[] args)
    {
        Person p = new Person
        {
            Name = "Tom",
            Age = 30
        };
    }
}

C# 9.0: with 표현식

record 타입은 객체 전체가 Immutable인 http://www.csharpstudy.com/latest/CS9-record.aspx타입인데, 만약 객체 중 일부만 변경하여 새로운 record 객체를 만들고 싶다면, C# 9에서 새로 도입된 with 키워드를 사용할 수 있다. 예를 들어, 아래 예제에서 Person 타입의 객체로 tom1을 만들었을 때, tom1 객체 중 나이만 변경하고 나머지 데이타는 동일하게 tom2 객체를 만들고 싶다면, 아래와 같이 with 키워드를 사용할 수 있다.

예제

// 예제(3)
Person tom1 = new Person
{
    Name = "Tom",
    Age = 30
};

Person tom2 = tom1 with { Age = 40 };

C# 9.0: record 객체 비교

record 타입은 Immutable인 타입으로 두 record 객체를 비교할 때, 객체 내의 값들이 동일한 지를 비교하는 경우가 더 많을 것이다. 이러한 맥락에서 record 타입의 Equals() 메서드는 record 객체의 데이타 값들이 동일한 지를 체크하고 데이타가 동일하면 참을 리턴한다. 아래 예제에서 두 객체의 레퍼런스는 다를 것이므로 ReferenceEquals()은 false를 리턴하고, 두 객체의 데이타가 동일하므로 Equals()은 true를 리턴한다.

예제

// 예제(4)
Person p1 = new Person
{
    Name = "Tom",
    Age = 30
};

Person p2 = new Person
{
    Name = "Tom",
    Age = 30
};

bool same = p1.Equals(p2); // true

bool b = ReferenceEquals(p1, p2);  //false

C# 9.0: Positional record

record 타입은 아래 예제(5)에서 보는 바와 같이 생성자(constructor)와 Deconstructor를 사용할 수 있는데, 이들은 Positional record를 사용하면 생성자(constructor)와 Deconstruct를 정의할 필요 없이 아래 예제(6)과 같이 간결하게 표현할 수 있다. Positional record는 말 그대로 멤버의 위치가 중요하면, 그 위치대로 데이타는 넣거나 가져올 수 있다. 예제(7)은 Constructor와 Deconstructor를 사용하는 예이다.

예제

// 예제(5) 레코드에 Constructor/Deconstructor 사용
public record Person
{
    public string Name { get; init; }
    public int Age { get; init; }
    public Person(string name, int age)
        => (Name, Age) = (name, age);
    public void Deconstruct(out string name, out int age)
        => (name, age) = (Name, Age);
}

// 예제(6) Positional record
public record Person(string Name, int Age);

// 예제(7) 
class Program
{
    static void Main(string[] args)
    {
        // Constructor 사용
        Person tom = new Person("Tom", 30);

        // Deconstructor 사용
        var (name, age) = tom;

        Console.WriteLine($"{name}, {age}");
    }
}

C# 9.0: 파생 record

record 타입은 상속을 지원하며, 파생 클래스를 정의하는 것과 동일한 방식으로 파생 record를 만들 수 있다. 파생 record 타입에서도 with 표현식과 Equals 객체 비교 등이 동일하게 적용된다.

예제

// 예제(8) 파생 record
public record Person
{
    public string Name { get; init; }
    public int Age { get; init; }
}

public record Employee : Person
{
    public int Id { get; init; }
}

class Program
{
    static void Main(string[] args)
    {
        Person p1 = new Employee
        {
            Id = 1001,
            Name = "Tom",
            Age = 30
        };
    }
}

 

http://www.csharpstudy.com/latest/CS9-record.aspx

'coding > c#' 카테고리의 다른 글

C# byte[]  (0) 2021.12.21
Encoding.UTF8.GetBytes  (0) 2021.12.20
mssql 설치  (0) 2021.12.20
C# 네트워크 클래스  (0) 2021.12.20
C# 공부 링크  (0) 2021.12.17