[C#] 문자열 보간에서 반복문 사용

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개의 좋아요

한 줄 축약 너무 좋습니다!!

1개의 좋아요

기존에는 이렇게 코딩해야 했던 것을,

        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개의 좋아요

어… 음… F#이 생각나는 코드네요

1개의 좋아요