Keeping code structure with string literal that uses whitespace
因此,我在提出搜索字词时遇到了一个奇怪的问题。 如果我的程序中有多行字符串文字,是否可以在不向字符串文字添加多余空格的情况下使代码缩进保持一致?
例如:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | 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); } } |
可能只是我的OCD在讲,但无论如何都可以保持程序的缩进,而无需在字符串中添加不必要的空格,也不必逐行构建它(实际字符串是超长字符串。格式为20?行 里面有12个变量)?
我将其完全抽象为一个单独的静态类或资源:
1 2 3 4 5 6 7 8 9 | 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"; } |
用法如下:
1 | stringLiteral = String.Format(MyStringResources.StringLiteral, var1, var2, var3); |
更好的是,通过这种方式,您可以拥有一个不错的函数,该函数需要一定数量的预期变量:
1 2 3 4 5 6 7 8 9 10 11 12 13 | 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); } } |
这样一来,您就不会意外遗漏变量(甚至可能强烈将其键入数字,布尔值等)。
1 2 | stringLiteral = MyStringLiteralBuilder.Build(var1, var2, var3); stringLiteral = MyStringLiteralBuilder.Build(var1, var2); //compiler error! |
当然,在这一点上,您可以使用这些构建器执行几乎任何您想做的事情。为您的程序中每个特殊的大" stringLiteral"创建一个新的生成器。也许不是让它们
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | 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(); |
在另一个文件中定义字符串常量,然后在代码中使用标识符。如果您需要翻译,检查合规性等内容,则最好将所有字符串都放在一个地方。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | 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 " + "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); } } |
不漂亮,但是可以用。
另一个"解决方案"是将每个这样的字符串包装在#region中并将其折叠。这并不能真正解决问题,但至少可以使代码少一点麻烦。
在我的情况下,可以这样制作扩展方法:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 | 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)))); } } |
将@逐字字符串和较新的$字符串插值结合使用时,可以应用以下技巧:在{和}中,它是一个表达式(因此,代码),而不是字符串数据。将换行符和缩进放置在此处,它将不会显示在格式化字符串中。如果您的文本不包含表达式,则必须使用一个空表达式。我已经尝试过{},但不幸的是,这不起作用:表达式预期错误。最少使用{nl},将空字符串分配给nl。换行nl或{wrap}或类似的东西。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | using System; namespace ConsoleApplication6 { class Program { static void Main(string[] args) { int count = 123; string nl = string.Empty; Console.WriteLine($@"Abc {count} def {count } ghi { count} jkl{nl } mno"); Console.ReadLine(); } } } |
输出:
abc 123 def 123 ghi 123 jkl mno
C#语言的语法允许使用两种方式指定字符串文字:
-
here-doc / at-string(
@"..." ),它可能跨越源文件行,或者 -
序数字符串文字(
"..." ),可能不是。
获得所需效果的其他方法:
将您的字符串放入资源文件。这使得本地化更容易进行。
将它们作为嵌入式(文件)资源添加到您的程序集中:
- http://support.microsoft.com/kb/319292
- 如何在.NET程序集中嵌入文本文件?
另一种选择是,根据其他答案尝试使它看起来更好:
1 2 3 4 5 6 7 | static readonly string MultilineLiteral = string.Join( Environment.NewLine , new string[]{ @"line 1" , "line 2" , @"line 3" , . . . "line n" , }) ; |
我也遇到过这个问题。
有时我用
)将整个内容放在一行上。
有时候,我只是忽略了丑陋的代码格式。
其他时候,我把文本放在其他地方-我认为在c#中,您有#define,甚至在单独的文件或数据库中,具体取决于所讨论的字符串。您仍然必须替换变量-在C#中,我认为您使用string.Format?
我希望这足以让您开始解决方案。