C#의 문자열 보간은 강력합니다. 가독성도 좋고 컴파일 시점에서 해석하기 때문에 오류 확인도 쉬운데요, 한가지 큰 단점이 있습니다.
다음의 경우를 생각해보죠. 다음의 문자열을 생성하고 싶은데 보간된 문자열로 표현할 방법이 없습니다.
nums {
1, 2, 3, 4, 5,
}
| 일반적인 방법
$@"nums {{
{numsText}
}}"; // 여기서 numsText는 "1, 2, 3, 4, 5,"
반복문을 보관된 문자열로 표현할 수 있으면 참 좋을텐데요 다음의 메소드 확장으로 유사하게 사용할 수 있습니다.
public static class StringBuilderExtension
{
public static StringBuilder Foreach<T>(this IEnumerable<T> enumerable, Action<StringBuilder, T> funcCallback)
{
var result = new StringBuilder();
foreach (var item in enumerable)
{
funcCallback?.Invoke(result, item);
}
return result;
}
}
using System.Text;
var nums = new[] { 1, 2, 3, 4, 5 };
var result =
$@"nums {{
{nums.Foreach((s, n) => s.Append(n).Append(", "))}
}}";
Console.WriteLine(result);
| 출력
nums {
1, 2, 3, 4, 5,
}
4개의 좋아요
기존에는 이렇게 코딩해야 했던 것을,
var sb = new StringBuilder();
sb.Append(@"
namespace Autogen.Enum
{
public static partial class EnumExtensions
{");
foreach (var enumToGenerate in enumsToGenerate)
{
sb.Append(@"
public static string ToStringFast(this ").Append(enumToGenerate.Name).Append(@" value) => value switch
{");
foreach (var (Member, Text) in enumToGenerate.Values)
{
sb.Append(@"
").Append(enumToGenerate.Name).Append('.').Append(Member).Append(" => ")
.Append(Text).Append(",");
}
sb.Append(@"
_ => value.ToString(),
};");
}
확장 메소드를 이용하면 다음처럼 표현할 수 있습니다.
var result = $@"
namespace Autogen.Enum
{{
public static partial class EnumExtensions
{{{enumsToGenerate.ForEach((s, i1) => s.Append($@"
public static string ToStringFast(this {i1.Name} value) => value switch
{{{i1.Values.ForEach((s, i2) => s.Append($@"
{i1.Name}.{i2.Member} => {i2.Text},"
))}
_ => value.ToString(),
}};"
))}
}}
}}";
2개의 좋아요
이 버젼이 조금 더 깔끔한 것 같습니다.
public static class StringBuilderExtension
{
public static StringBuilder ForEach<T>(this IEnumerable<T> enumerable, Func<T, string> funcCallback)
{
var result = new StringBuilder();
foreach (var item in enumerable)
result.Append(funcCallback?.Invoke(item));
return result;
}
}
var result = $@"
namespace Autogen.Enum
{{
public static partial class EnumExtensions
{{{enumsToGenerate.ForEach(i1 => $@"
public static string ToStringFast(this {i1.Name} value) => value switch
{{{i1.Values.ForEach(i2 => $@"
{i1.Name}.{i2.Member} => {i2.Text},"
)}
_ => value.ToString(),
}};"
)}
}}
}}";
3개의 좋아요
이번 C#11의 원시 문자열 리터럴 업데이트에 의해 다음 처럼 쓸 수 있게 되었습니다.
var result = $$"""
namespace Autogen.Enum
{
public static partial class EnumExtensions
{{{enumsToGenerate.ForEach(i1 => $$"""
public static string ToStringFast(this {{i1.Name}} value) => value switch
{{{i1.Values.ForEach(i2 => $$"""
{{i1.Name}}.{{i2.Member}} => {{i2.Text}},
""")}}
_ => value.ToString(),
}
""")}}
}
}
""";
1개의 좋아요