使用使用空格的字符串文字保持代码结构

Posted

技术标签:

【中文标题】使用使用空格的字符串文字保持代码结构【英文标题】:Keeping code structure with string literal that uses whitespace 【发布时间】:2013-06-22 20:48:36 【问题描述】:

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

例如:

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 个变量)?

【问题讨论】:

您可以添加伪代码来演示所需的缩进和不需要的空格。 @TimSchmelter 我只想缩进字符串以匹配其余代码的缩进,但是如果我这样做,它会在字符串文字中添加制表符/空格。我希望代码在功能上是相同的,但带有标签的字符串以匹配程序其余部分的缩进。 也许字符串很长,您可以考虑将其移动到单独的静态类/成员或某些资源中。 @ChrisSinclair 在我的程序中,它实际上不是静态字符串,而是在运行时使用多个变量在大字符串文字上使用巨大的 string.format() 构建的。我将编辑问题以使其更清楚。 KEvin,我其实写了一个个人小库,叫做“BetterStringLiterals”。你要吗?它可以让你做到这一点。 【参考方案1】:
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);
    

不漂亮,但很管用。

【讨论】:

我假设 OP 希望保留逐字字符串并避免在末尾使用 \r\n" + 可能......但 OP 必须做出选择。没有什么神奇的方法可以适应缩进而不使用\r\n" +。他可以这样做,或者 OP 中的方式 - 或者实际上他可以像 @Zdravko 那样做,这可能要好得多......但那是完全不同的事情。 +1 表示显而易见。该语言只提供了两种构造字符串文字的方法——here-doc/at-string (@"..."),允许跨越源文件中的行或传统的字符串文字 ("..."),它可能不跨越源文件中的行。编译器和优化器会处理常量折叠,因此运行时性能不是问题。 是的,这就是在我将其更改为字符串文字之前代码的外观。文字更清晰,但只是让我对我所有逻辑中间的缩进感到困扰。将其作为资源对我来说最有意义。【参考方案2】:

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

【讨论】:

其实我没有想过这是真的,但我可以让它包含 0...等作为资源。这被认为是不好的做法吗? 我不明白为什么这是一个不好的做法。我的资源中有 0 1...它仍然比在所有代码中包含字符串要好...【参考方案3】:

我也遇到过这个问题。

有时我将整个内容与\n(或\r\n 用于dos/windows)放在一条线上。

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

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

我希望这足以让您开始寻找解决方案。

【讨论】:

【参考方案4】:

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

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();

【讨论】:

我喜欢,谢谢你的回答!现在回想起来似乎很明显。 @KevinDiTraglia 没问题!很高兴我们能提供帮助。 我只希望我能在 900 岁时成为一名专业的放风筝的人 HrrRHrhhrRHm,当900 years old you reach,放风筝一样好,你不会,hRRhrrmRMR?【参考方案5】:

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

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

获得你想要的效果的其他方式:

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

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

    http://support.microsoft.com/kb/319292 How to embed a text file in a .NET assembly?

另一种选择,与其他答案一样,试图让它看起来更好:

static readonly string MultilineLiteral = string.Join( Environment.NewLine , new string[]
                                          @"line 1" ,
                                           "line 2" ,
                                          @"line 3" ,
                                          . . .
                                          "line n" ,
                                          ) ;

【讨论】:

【参考方案6】:

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

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

【讨论】:

有趣的想法,遗憾的是它读起来有点难看,让没有看过它的人感到困惑。我敢肯定附加 string.empty 也是有代价的。太糟糕了,逐字字符串上没有忽略返回/多个空格标志。【参考方案7】:

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

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))));
    

【讨论】:

我不认为你可以单独分割一个字符串。我首先声明string[] newline = new[] Environment.NewLine ,第二个要拆分的arg 是StringSplitOptions.None,然后在String.Join 中,我使用Environment.NewLine 作为第一个arg。【参考方案8】:

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

【讨论】:

以上是关于使用使用空格的字符串文字保持代码结构的主要内容,如果未能解决你的问题,请参考以下文章

代码实现:输入一行字符,分别统计出其中英文字母空格数字和其它字符的个数。

css中空格怎么打

最长回文字串暴力

如果 HTML 包含空格,则 JQuery HTML 未终止的字符串文字错误

敲代码指向光标会覆盖下一个字符,无法用空格换行,无法打字或打字会把后面的文字覆盖解决方法

java如何打印出任意给定的空格