글쓴이는 Dictionary<string, string>
를 예로 들어서 유형 별칭을 이용해 그 의미를 명확하게 하고자 합니다.
// Create aliases
using UserId = string;
using ProjectId = string;
// Use the type aliases
// ✅ It's clear that the first string is a UserId and the second string is a ProjectId
_ = new Dictionary<UserId, ProjectId>();
이 방식이 거추장스러워 보이는지, 아니면 의미 있어 보이는지 어떻게 생각하시나요?
8개의 좋아요
나쁘진 않은거 같은데…
안그래도 네이밍할 때 이름 모잘라서 저거까지 쓰는거 좀 부담이긴 하네요 ㅠㅠ
예를 들어 언급된 유형 별칭
생기면 아래와 같이 되는데…
using UserId = string;
class Message
{
UserId UserId { get }
}
5개의 좋아요
code
4월 23, 2024, 2:00오전
3
단일 타입에 대한 별칭은 호불호가 있어 보이긴 하는데
선택의 문제일거 같습니다.
이번에 업데이트 되면서 편했던건
tuple에 대해 별칭이 가능해 졌던거 입니다.
기존에는 안됐던 거고 쓸일이 은근 있어서 편했습니다.
다음 버전에 바라는 것은
using 에 대한 using 입니다.
using Chapter = List<string>;
using Book = List<Chapter>;
대충 요런 식으로 하는게 가능 하면 어떨까 싶네요.
4개의 좋아요
그라목손
4월 23, 2024, 2:07오전
4
C++11에서 지원하는 별칭과 같네요
C++에서 typedef 대신 저런 식으로 쓰기도 합니다.
5개의 좋아요
BOBx5
4월 23, 2024, 2:56오전
5
저라면 Strongly-Type 인 객체를 record 한정자 사용해서 선언하겠습니다.
저런걸 한 파일 내에서만 일어나는게 아니고 여러 파일에서 매번 넣어줘야하는거 자체도
또 하나의 보일러플레이트 아닌가 싶습니다 ㅋㅋㅋㅋ
public record UserId
{
public required string Value { get; init; }
}
public record ProjectId
{
public required string Value { get; init; }
}
4개의 좋아요
suwoo
4월 23, 2024, 4:17오전
6
저도 C에서 하던 그 모습이 생각나는걸요 ㅠㅠ
차라리 저렇게 쓴다치면
Dictionary<TKey,Tvalue>
가 아니라
List<(string userId, string projectId)
가 더 나아보이고
@BOBx5 님께서 언급한 Record나,
@code 님께서 말씀해주신 tuple이 나아보입니다.
3개의 좋아요
그라목손님 말씀대로 C++에서 많이 쓰는 방식인데요. C++자체적으로 지원하는 것들이 보통 접미사로 _t를 붙입니다. (ex: int8_t, int32_t, uint8_t, uint32_t,… )
사용해 본 바로는 자주 쓰는 것들일 경우 쓸만합니다.
물론 저도 접미사를 붙이죠.
한눈에 알아볼 수 있다면 나쁘지 않다고 생각 합니다.
4개의 좋아요
주제와 상관은 없는데 record 기본 생성자 대신 속성으로 예시를 표현했는지 궁금합니다. 특별한 이유가 없거나 있다면 그 이유를 알 수 있을까요?
2개의 좋아요
tkm
4월 23, 2024, 5:52오전
9
예전에 이렇게 사용해본적이 있었는데, 위 예시의 경우, IDE에서 모든 string이 UserId로 표시되길래 지웠습니다…
4개의 좋아요
rkttu
4월 25, 2024, 10:38오후
10
형식 타입을 매번 새로 지정해야 하는 delegate (특히 Action이나 Func 처럼 받는 인자 수 자체가 많고 다양한 타입)나 Tuple 같은 타입에 효과적인 수단… 이긴 한데, C/C++의 typedef나 #define처럼 프로젝트 전체에 걸쳐 쓸 수 있는 것은 아니다보니 개인적으로는 좀 애매하다고 생각하는 편입니다.
의견을 달다가 생각나서 global using으로 alias를 선언할 수 있던가? 해서 살펴보니 가능하군요 ㅎㅎ 다만 이것도 프로젝트 권역 밖으로 넘어가면 유지가 안되는 정보긴 합니다만, 그래도 global using이 나오기 전에는 기껏해야 파일 안에서밖에 쓰임새가 없어서 애매하다고 생각했는데 이제 쓰임새가 좀 생긴 것 같습니다 ㅎㅎ
(아, 이것도 우회책이라면 우회책이긴 하겠네요. 여러 프로젝트에 걸쳐 유효하게 만드는 방법으로 Shared Project가 있긴 하겠습니다. 다만 이것도 C# 10 이상을 지원하는 닷넷 프로젝트 간에만 허용되는 부분일거고, 닷넷 프레임워크 프로젝트 쪽에서는 nullable 타입을 강제 주입할 떄처럼 컴파일러 버전을 강제로 높이는 방식으로 처리가 가능할지는 시험해보진 않았습니다.)
예:
global using Sample = System;
3개의 좋아요
BOBx5
6월 12, 2024, 3:41오후
11
@dimohy
오랜만에 들어와서 저때 무슨 생각으로 작성한건지는 불분명하네요.
다만 Strong-Type
을 언급한걸로 보아 다음 같은걸 설명하려던 것 같습니다.
UserId
라는 Immutable 한 객체를 record 한정자를 이용해서 생성하려는 목적입니다.
public record UserId
{
public string Value { get; init; }
private UserId(string value)
{
this.Value = value;
}
public override string ToString()
{
return this.Value;
}
public static UserId Create()
{
return new UserId(Guid.NewGuid().ToString());
}
public static UserId Parse(string value)
{
if(!Guid.TryParse(value, out Guid guid))
{
throw new InvalidUserIdFormatException();
}
return new UserId(guid.ToString());
}
public static bool TryParse(string value, out UserId? userId)
{
if(!Guid.TryParse(value, out Guid guid))
{
userId = null;
return false;
}
var userId = Parse(guid.ToString())
return true;
}
}
예시가 완벽하진 않지만 위와 같은 record class 를 통해서 얻을 수 있는 이점이 있습니다.
UserId
의 생성자가 private
으로 막혀있기 때문에 UserId
의 생성은 순수하게 다음 3가지의 static
메서드로만 가능합니다.
Create()
Parse(...)
TryParse(...)
이를 통해 정상적은 Guid
의 길이인 36
자가 아닌 24
자만 갖는 UserId
인스턴스의 생성을 코드적으로 제한할 수 있습니다.
또 하나의 이점은 해당 값의 Property를 추가적으로 늘리는 것 만으로
DB 관점에 다중키를 갖는 객체의 키 값을 두개의 프로퍼티로 관리하는 것이 아닌,
하나의 객체인 것 처럼 코드상에서 관리 & 비교(by record의 특성)할 수 있게됩니다.
다만, 다 쓰고 나니 저도 무슨 맥락에서 저 글을 이해하고 저렇게 댓글을 작성한건지는 잘 모르겠습니다…
4개의 좋아요
마수리
7월 15, 2024, 9:14오전
12
이 글 머리속에 계속 기억해두다가 ㅋㅋㅋ 써보았는데 표현력이 많이 좋아 지는 것 같아서 좋은 것 같네요!!
매번 Dictionary
선언할 때마다 key
, value
데이터를 표현하기 위해 이름을 고민하곤했는데 이 방법을 쓰니 한번에 의미가 표현되니 좋은 것 같습니다!
1개의 좋아요
suwoo
7월 15, 2024, 10:56오후
13
실례가 안된다면 혹시 사용 중이신 예제를 보여주실 수 있을까요?
음… 제가 느끼기엔 KeyValuePair에서 이미 Key와 Value라는 이름이 있는데,
그걸 “다른 의미로” 부여해서 쓰는 걸로 느껴져서 좀 이상하다는 느낌이 들었습니다.
물론 그렇게 쓰면 편한 경우가 많은 경우도 많이 봐서… “틀렸다” 라고 생각하지는 않습니다 ㅠ
그런데,
묘하게 옛날 어느 은행쪽 코드에서 메서드의parameters를 Dictionary로 넘기는 걸 봤다는 괴담이 생각 났어요.
공식 문서에 나온대로 tuple타입이 제일 최적의 사용례인거같아요(타입 서술이 귀찮고 의미부여가 힘들기 때문) 나머지는 쓸일이 있을까 싶네요.
마수리
7월 16, 2024, 6:01오전
15
실례될리가 있습니까?!
Dictionary<string, string> renameDictionary;
이라고 선언할 것을
Dictionary<ActualName, RenameName> renameDictionary
이렇게 선언했어요
사용한 방법은
// 특정 파일 이름은 renameDictionary에 있는 다른 이름으로 교체한다.
if(renameDictionary.ContainsKey(fileName))
fileName = renameDictionary[fileName]
이렇게 사용하니 key는 실제 파일 이름이고 value는 바뀌어야할 이름이다. 라고 선언에서 표현한 것 같아서 좋은 사용방법이 됐다고 생각했습니다.
1개의 좋아요
네임스페이스
7월 20, 2024, 10:01오후
16
음⋯ 컨벤션이 아니라면 이런게 남발되어있는 남의 코드 읽을 땐 짜증날 것같네요 ㅎㅎㅎ
using UserAge = int;
using AgedUsers = int;
using UserIdString = string;
using UserShortName = string;
Dictionary<UserAge, AgedUsers> _ageUsers = [];
Dictionary<UserIdString, UserShortName> _idUserName = [];
이 것보다는 아래가 구체성/사용성 측면에서 좋아 보이고, 실제로 제 코딩 관습입니다.
/// <summary>
/// User.Age, 그 나이의 사용자 수
/// </summary>
Dictionary<int, int> _ageUsers = [];
/// <summary>
/// User.Id.ToString(), User.ShortName
/// </summary>
Dictionary<string, string> _idUserName = [];
2개의 좋아요
마수리
7월 23, 2024, 6:49오전
18
잘 지은 이름으로 Dictionary
의 키와 값을 구분하는 방법이 가장 범용적인 방법인 것 같네요