(C#) Serialization [3]
포스트
취소

(C#) Serialization [3]

지난 글(Serialization [2])에 이어서 코드 효율성과, 자동화를 계속 진행한다.

💻 코드

하드코딩 가독성

변수 사이즈만큼 count에 더해주는 작업을 했었다. 이렇게 숫자로 넣기 보다는 가독성을 위해 sizeof()를 사용하는 것이 더 좋다.

1
2
3
4
5
6
7
// 하드코딩 보다는
count += 2;
count += 8;

// sizeof로 무엇을 넣는 목적인지 보여주는게 좋음.
count += sizeof(ushort);
count += sizeof(long);

Write 수정

앞전에는 Span을 생성하여 바로 넣는 작업을 진행했었다.

하지만 이렇게 사용하는 것 보다 Span을 미리 생성하여 Slice로 범위를 지정해주는 것이 더 가독성 좋으므로 변경해준다.

Read()ReadOnlySpan도 똑같이 작업해준다.

1
2
3
4
5
6
7
8
9
ArraySegment<byte> segment = SendBufferHelper.Open(4096);

// [ 변경 전 ]
BitConverter.TryWriteBytes(new Span<byte>(segment.Array, segment.Offset + count, segment.Count - count), this.packetId);

// [ 변경 후 ]
// Span : 배열의 일부분을 가리키는 것
Span<byte> s = new Span<byte>(segment.Array, segment.Offset, segment.Count);
BitConverter.TryWriteBytes(s.Slice(count, s.Length - count), this.packetId);

string 관리

int, long 같은 변수는 크기가 고정되어 있지만, string같은 경우 가변적인 크기를 가지고 있으므로 관련 구현이 필요하다.

그리고 UTF-8, UTF-16 중에서 고민을 해봐야 되는데 기본적으로 C#에서 UTF-16을 선호하고 있기 때문에

굳이 UTF-8로 맞춰서 수정하기 보다는 구현에 있어서 UTF-16으로 맞춰주기로 한다.

우선 string의 유무를 확인하기 위해 2바이트의 문자열크기 패킷을 먼저 받고 그다음에 문자열을 받도록 진행한다.

1
2
3
4
5
6
7
8
9
10
// string 문자열 크기 공간(ushort) +
ushort nameLen = (ushort)Encoding.Unicode.GetByteCount(this.name);
success &= BitConverter.TryWriteBytes(s.Slice(count, s.Length - count), nameLen);
count += sizeof(ushort);

// name 문자열 공간(nameLen) +
Array.Copy(Encoding.Unicode.GetBytes(this.name), 0, segment.Array, count, nameLen);
count += nameLen;

// [string Length(2)][string(...)]

UTF-16 방식의 바이트 변환법은 Encoding.Unicode를 사용한다.

현재 구현된 코드도 괜찮지만 크기를 뱉어내며 namesegment에 집어넣는 방법을 동시에 진행하는 더 효율적인 코드도 존재한다.

string 값을 먼저 넣다보니 크기를 고려하여 구현해야되고 마지막에 count를 해주기 때문에 헷갈릴 수 있다.

1
2
3
4
ushort nameLen = (ushort)Encoding.Unicode.GetBytes(this.name, 0, this.name.Length, segment.Array, segment.Offset + count + sizeof(ushort));
success &= BitConverter.TryWriteBytes(s.Slice(count, s.Length - count), nameLen);
count += sizeof(ushort);
count += nameLen;


💡 참고

이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.