我在读比尔·瓦格纳的《有效C》。在项目14-最小化重复初始化逻辑中,他展示了在构造函数中使用新的可选参数特性的以下示例:
public MyClass(int initialCount = 0, string name ="")
注意他用了""而不是string.Empty。他评论说:
You'll note [in an example above] that the second constructor specified"" for the default value on the name parameter, rather than the more customary string.Empty. That's because string.Empty is not a compile-time constant. It is a static property defined in the string class. Because it is not a compile constant, you cannot use it for the default value for a parameter.
如果我们不能在所有情况下都使用string.Empty静态,那么这是否会破坏它的目的?我想我们应该使用它来确保我们有一个独立于系统的方法来引用空字符串。我的理解错了吗?谢谢。
更新只是后续评论。根据msdn:
Each optional parameter has a default value as part of its definition. If no argument is sent for that parameter, the default value is used. Default values must be constants.
然后我们也不能使用System.Environment.NewLine,或者使用新实例化的对象作为默认值。我还没用过VS2010,这真让人失望!
- 我不知道空字符串在不同平台上的表示方式有什么不同。它不像新线。
- 是的,我在想,那么它只是在代码中看起来更好吗?
- clr而不是"system"是决定"是否为空字符串的因素。因此,我认为您可以安全地假设"是一种独立于系统的引用兼容CLR实现上字符串的方法"。
- "系统独立"?呃,与特定的系统不同????)
- 根据msdn:此字段的值是零长度字符串""。因此,正如许多人指出的那样,这显然与平台独立无关。但人们似乎还不知道为什么要使用它!
- 我们曾经开玩笑说,如果微软开玩笑改变了字符串的值,那么有多少代码会被破坏。空的改成其他的值:)我个人大量使用它,除了我不能使用的地方。我只是觉得它更干净,尽管这是一种观点
- 我想指出的是,新行在字符串中的表示方式在不同的平台之间没有区别;它总是"n"。不同之处在于它在文件中的表示方式,并且您可以在任何系统上的文件中获得任何行尾样式,因此它可以在文件读取代码中自动检测和处理,就像字符编码一样。对于要写入文件的内容,建议使用system.environment.newline常量,但如果始终这样做,"n"是安全的。
- @吉米兰多姆,你确定吗?也许这只是我的Visual Studio调试器窗口/监视部分,但当我查询什么环境时,换行符通常是:
?但您肯定,如果我只是使用它,它会拿起它并与它一起运行…如果我想用它作为分隔符来拆分从读取文件中提取的字符串?
- @Jimrandomh"我只是想指出,新行在字符串中的表示方式在平台之间没有区别"——这与本次讨论完全无关。不同之处在于它在文件中的表示方式——这就是system.environment.newline的价值所在。您可以在任何系统的文件中获得任何行尾样式——同样不相关(而且不是真的,除非您认为唯一的系统是Windows系统)。system.environment.newline是默认表示,它是写入时的表示。
- 为什么字符串不可能重复。清空常量?
对于C 2.0编译器,几乎没有指向String.Empty,事实上,在许多情况下,它是悲观的,因为编译器可以内联一些对""的引用,但不能对String.Empty执行相同的操作。
在C 1.1中,避免创建大量独立的对象(所有这些对象都包含空字符串)是很有用的,但是那些日子已经过去了。""工作得很好。
- 即使在.NET 1.1中,它也不会创建"大量"独立对象。我不记得1.1和2.0在这方面的区别,但它不像字符串文字interning只在2.0中引入。
- 谢谢你的澄清。我环顾四周,没有找到关于C 2.0中变化的一个很好的总结,尽管我确信我以前读过一篇。我确实找到了2008年的StackOverflow答案,其中有一些链接指向更多的技术信息。stackoverflow.com/questions/151472/…
- 我会点头的,虽然我不喜欢说有点指向线。空的,因为我使用它相当严重。我觉得它看起来很干净,尽管这是我个人的观点。有很多地方字符串。空的不能使用,在这些情况下使用"我没有问题
- 我用过string.empty,只是因为它是"推荐"的操作,但我从来都不喜欢它。字面上的"似乎是直截了当,清晰明了的,而且有了弦乐节拍,这也很经济。
- 我发现用字符串快速识别一个空字符串要容易得多。空字符串比看两次"以确保它没有撇号或类似的东西隐藏在里面"要容易得多。+不过,我想解释一下。
- + 1克里斯。同样,在vs中,您不能搜索的用法(除了执行标准查找,它还将返回每个文本匹配,包括注释和标记)。您可以使用string.empty搜索特定于代码的用法。
如果您真的想将空字符串用作可选参数值,那么没有什么可以阻止您为其定义自己的常量:
1 2 3 4 5 6
| const string String_Empty ="";
public static void PrintString(string s = String_Empty)
{
Console.WriteLine(s);
} |
[顺便说一句,一个原因是喜欢String.Empty比"",一般来说,在其他答案中没有提到,是有各种Unicode字符(零宽度连接符等)是有效地肉眼看不见的。所以看起来像""的东西不一定是空字符串,而对于String.Empty,你确切地知道你在使用什么。我认识到这不是常见的bug源,但这是可能的。]
- + 1。你让"string.empty"看起来像是有目的的!
- 也有不可见的标识符字符,所以看起来像字符串_empty的东西不一定是空的。Unicode标准在安全考虑方面有一个很大程度上被忽略的章节。
从最初的问题:
I thought that we would use it to be sure that we have a system-independent means of referring to the empty string.
空字符串在不同系统中有什么不同?它总是一个没有字符的字符串!如果我发现一个实现中string.Empty ==""返回了false:)这与Environment.NewLine不同,我会非常害怕。
从反恐组织的赏金岗位:
I want String.Empty can be used as a default parameter in the next C# release. :D
那当然不会发生。
虽然我个人也希望使用一种完全不同的默认机制,但自启动以来可选参数在.NET中的工作方式始终意味着在元数据中嵌入常量,以便调用代码可以在没有提供相应参数的情况下将该常量复制到调用站点。
对于String.Empty,使用""会满足您的需要,使用字符串文字会很痛苦吗?(我在任何地方都使用文字-我从未使用过String.Empty,但这是另一种说法。)
这就是我对这个问题感到惊讶的地方——抱怨的焦点是一些实际上不会引起真正问题的事情。在您希望在执行时计算默认值的情况下,这一点更为重要,因为它实际上可能会有所不同。例如,我可以想象这样的情况,您希望能够使用DateTime参数调用一个方法,并将其默认为"当前时间"。目前,我所知道的唯一一个模糊优雅的工作环境是:
1 2 3 4
| public void RecordTime(string message, DateTime? dateTime = null)
{
var realDateTime = dateTime ?? DateTime.UtcNow;
} |
…但这并不总是合适的。
总之:
- 我非常怀疑这是否会成为C的一部分。#
- 对String.Empty来说,无论如何都是毫无意义的。
- 对于其他价值观来说,它们的价值并不总是相同的,这确实是一种痛苦。
- 这实际上是解决问题的好方法。同样的事情也可用于携带/设置其他设备相关变量,如Environment.Newline。示例中唯一缺少的就是检查变量是否为空,并向开发人员抛出异常,告诉他虽然可以为空,但不被接受。或者类似的东西。但我真的很喜欢这个!你还有其他的注意事项吗?
- @maxovrdrv:你不希望它为空是一个错误——关键是当它为空时,你计算一个默认值。警告是,它不允许将空值作为有效值本身传递。
- 你完全正确。我的错。--是的,那将是唯一真正的警告,不是吗…这还不错。再次:我真的很喜欢这个解决方案!:)感谢您发布!:)
我从不用绳子。空的,我看不出它的意义。也许它可以让那些刚开始编程的人更容易一些,但我怀疑它是否有用。
- 也许它可以防止混淆""和"",但我不能说""是所有这些常见的。
- 我建议那些看不出两者区别的人要么戴上更好的眼镜,要么降低屏幕分辨率。我视力不好,我记不起曾经犯过这样的错误(而且我必须处理很多包含这两个错误的代码)。
- 空字符串有助于找出程序员的确切意图。"不告诉任何关于意图的事情,如果程序员打算初始化像这样的变量"lol",但是忘记了……在这种情况下,有无限的可能性和字符串,空的很有用,并且做得更好
我认为字符串背后的想法。空的是它增强了可读性。它不像newline那样,在不同的平台上表示它的方式有任何区别。它是asname,不能在默认参数中使用。但是,如果您在Windows和Linux上的Mono之类的设备之间进行端口连接,则不会导致任何问题。
- 我认为你可能是对的,因为有些人认为String.Empty更易读。…但就个人而言,我认为这有点疯狂。""可能是最常见的字符串,而且每个人都看过十亿次,那么它是如何不可读的呢?String.Empty的用处与Int32.Zero差不多。
作为Fyi,似乎对传递给属性构造函数的值施加了相同的约束——它们必须是常量。因为string.empty被定义为:
1
| public static readonly string Empty |
它不能被使用,而不是实际的常量。
我使用string.Empty纯粹是为了可读性。
如果以后有人需要读取/更改我的代码,他们就会知道我是想检查或设置一个空字符串。仅仅使用EDOCX1[1]有时会导致错误和混乱,因为我可能只是忘记了把我想要的字符串放在那里。
例如:
1 2 3 4
| if(someString == string.Empty)
{
} |
VS
1 2 3 4
| if(someString =="")
{
} |
第一个if声明对我来说似乎更为慎重和易读。因为这只是一种偏好,所以我真的不认为火车会因为使用""而不是string.Empty而崩溃。
也许这个问题的最佳解决方案是通过这种方式重载这个方法:
1 2 3 4
| public static void PrintString()
{
PrintString(string.Empty);
} |
- 如何回答上述问题?
- 它对可选参数的默认值有何帮助?