39

这是一个奇怪的问题,我在想出搜索词时遇到了麻烦。如果我的程序中有一个多行字符串文字,是否可以在不向字符串文字添加不需要的空格的情况下保持代码的缩进一致?

前任:

if (true)
{
    if (!false)
    {
        //Some indented code;
        stringLiteral = string.format(
@"This is a really long string literal
I don't want it to have whitespace at 
the beginning of each line, so I have
to break the indentation of my program
I also have vars here 
{0}
{1}
{2}",
var1, var2, var3);
    }
}

这可能只是我的强迫症说话,但无论如何要保持我的程序的缩进而不向字符串添加不需要的空格,或者必须逐行构建它(真正的字符串是一个超长的 string.format,即 20~ 行里面有12个变量)?

4

8 回答 8

11

我会将它完全抽象为一个单独的静态类或资源:

public static class MyStringResources
{
    public static readonly string StringLiteral = 
@"This {0} a really long string literal
I don't want {1} to have {2} at 
the beginning of each line, so I have
to break the indentation  of my program";

}

使用如下:

stringLiteral = String.Format(MyStringResources.StringLiteral, var1, var2, var3);

更好的是,这样你可以有一个很好的函数,它需要预期变量的数量:

public static class MyStringLiteralBuilder
{
    private static readonly string StringLiteral = 
@"This {0} a really long string literal
I don't want {1} to have {2} at 
the beginning of each line, so I have
to break the indentation  of my program";

    public static string Build(object var1, object var2, object var3)
    {
        return String.Format(MyStringResources.StringLiteral, var1, var2, var3);
    }
}

然后你就不会意外遗漏变量(甚至可能将它们强输入为数字、布尔值等)

stringLiteral = MyStringLiteralBuilder.Build(var1, var2, var3);
stringLiteral = MyStringLiteralBuilder.Build(var1, var2); //compiler error!

当然,在这一点上,您可以使用这些构建器做几乎任何您想做的事情。为程序中每个特殊的大“stringLiteral”创建一个新的构建器。也许static它们可以是您可以获取/设置关键属性的实例,而不是让它们成为实例,然后您也可以给它们起好听的名称:

public class InfoCardSummary
{
    public string Name { get; set; }
    public double Age { get; set; }
    public string Occupation { get; set; }

    private static readonly string FormattingString = 
@"This person named {0} is a pretty
sweet programmer. Even though they're only
{1}, Acme company is thinking of hiring
them as a {2}.";

    public string Output()
    {
        return String.Format(FormattingString, Name, Age, Occupation);
    }
}

var info = new InfoCardSummary { Name = "Kevin DiTraglia", Age = 900, Occupation = "Professional Kite Flier" };
output = info.Output();
于 2013-06-25T21:35:49.667 回答
10

就我而言,制作这样的扩展方法是可以接受的:

class Program
{
    static void Main(string[] args)
    {
        var code = $@"
            public static loremIpsum(): lorem {{
                return {{
                    lorem: function() {{
                        return 'foo'
                    }},
                    ipsum: function() {{
                        return 'bar'
                    }},
                    dolor: function() {{
                        return 'buzz'
                    }}
                }}
            }}".AutoTrim();

        Console.WriteLine(code);
    }
}

static class Extensions
{
    public static string AutoTrim(this string code)
    {
        string newline = Environment.NewLine;
        var trimLen = code
            .Split(newline)
            .Skip(1)
            .Min(s => s.Length - s.TrimStart().Length);

        return string.Join(newline,
            code
            .Split(newline)
            .Select(line => line.Substring(Math.Min(line.Length, trimLen))));
    }
}

在此处输入图像描述

于 2017-11-23T16:12:16.767 回答
3
if (true)
{
    if (!false)
    {
        //Some indented code;
        stringLiteral = string.format(
                    "This is a really long string literal. " +
                    "I don't want it to have whitespace at " +
                    "the beginning of each line, so I have " +
                    "to break the indentation of my program " +
                    "I also have vars here: " +
                    "{0} " +
                    "{1} " +
                    "{2}",
                  var1, var2, var3);
          // OR, with lineskips:
        stringLiteral = string.format(
                    "This is a really long string literal\r\n" +
                    "I don't want it to have whitespace at \r\n" +
                    "the beginning of each line, so I have\r\n" +
                    "to break the indentation of my program\r\n"
                    "I also have vars here\r\n" +
                    "{0}\r\n" +
                    "{1}\r\n" +
                    "{2}\r\n",
                  var1, var2, var3);
    }
}

不漂亮,但它有效。

于 2013-06-25T21:28:20.760 回答
3

在另一个文件中定义字符串常量并在代码中使用标识符。如果您需要翻译、审查合规性等,无论如何都将所有字符串放在一个地方是一种很好的做法。

于 2013-06-25T21:31:39.533 回答
2

另一个“解决方案”是将每个这样的字符串包装在 #region 中并折叠它。这并没有真正解决问题,但至少它使代码不那么令人眼花缭乱。

于 2018-09-25T07:50:39.243 回答
1

C# 语言的语法允许指定字符串文字的两种方式:

  • 一个 here-doc/at-string ( @"..."),它可能跨越源文件行,或者
  • 一个普通的字符串文字 ( "..."),可能不是。

获得您想要的效果的其他方法:

  1. 将您的字符串放入资源文件中。这使得本地化更容易。

  2. 将它们作为嵌入式(文件)资源添加到您的程序集中:

另一种选择,在其他答案的脉络中,试图让它看起来更好:

static readonly string MultilineLiteral = string.Join( Environment.NewLine , new string[]{
                                          @"line 1" ,
                                           "line 2" ,
                                          @"line 3" ,
                                          . . .
                                          "line n" ,
                                          }) ;
于 2013-06-25T21:40:36.223 回答
1

当组合 @ verbatim 字符串和较新的 $ 字符串插值时,您可以应用以下技巧:在 { 和 } 中,它是一个表达式(因此是代码)而不是字符串数据。把你的换行符和缩进放在那里,它不会出现在格式化的字符串中。如果您的文本不包含表达式,您可以在需要换行的地方用 ' ' 表达式替换空格。

using System;

namespace ConsoleApplication6
{
    class Program
    {
        static void Main()
        {
            int count = 123;
            Console.WriteLine($@"Abc {count} def {count
                } ghi {
                count} jkl{' '
                }mno");
            Console.ReadLine();
        }
    }
}

输出:

Abc 123 def 123 ghi 123 jkl mno

于 2016-04-08T11:26:49.887 回答
-2

我也遇到过这个问题。

有时我把整个东西放在一条线上\n(或\r\n用于dos/windows)。

有时,我只是忽略了丑陋的代码格式。

其他时候,我将文本放在其他地方 - 我认为在 c# 中你有#define,甚至在单独的文件或数据库中,具体取决于所讨论的字符串。您仍然必须替换变量 - 在 c# 中我认为您使用 string.Format?

我希望这足以让您开始解决问题。

于 2013-06-25T21:32:17.590 回答