在C#中,我想用空字符串初始化字符串值.
我该怎么做?什么是正确的方法,为什么?
string willi = string.Empty;
Run Code Online (Sandbox Code Playgroud)
要么
string willi = String.Empty;
Run Code Online (Sandbox Code Playgroud)
要么
string willi = "";
Run Code Online (Sandbox Code Playgroud)
或者是什么?
我正在阅读Bill Wagner的Effective C#.在第14项 - 最小化重复初始化逻辑中,他显示了以下在构造函数中使用新的可选参数功能的示例:
public MyClass(int initialCount = 0, string name = "")
请注意,他使用""而不是string.Empty.
他评论道:
您将注意到[在上面的示例中]第二个构造函数为name参数指定了默认值,而不是更常用的
string.Empty.那是因为string.Empty它不是编译时常量.它是字符串类中定义的静态属性.因为它不是编译常量,所以不能将它用作参数的默认值.
如果我们不能string.Empty在所有情况下使用静态,那么这不是打败了它的目的吗?我认为我们会用它来确保我们有一个独立于系统的方法来引用空字符串.我的理解错了吗?谢谢.
更新
只是后续评论.根据MSDN:
每个可选参数都有一个默认值作为其定义的一部分.如果没有为该参数发送参数,则使用默认值.默认值必须是常量.
然后我们无法使用它们System.Environment.NewLine,或者使用新实例化的对象作为默认值.我还没有用过VS2010,这太令人失望了!
精简版:
C#代码
typeof(string).GetField("Empty").SetValue(null, "Hello world!");
Console.WriteLine(string.Empty);
Run Code Online (Sandbox Code Playgroud)
在编译和运行时,"Hello world!"在.NET 4.0及更早版本下提供输出,但""在.NET 4.5和.NET 4.5.1下提供.
如何像这样忽略对字段的写入,或者,谁重置该字段?
更长的版本:
我从来没有真正理解为什么string.Empty字段(也称为[mscorlib]System.String::Empty)不是const(aka.literal),请参阅" 为什么String.Empty不是常量? ".这意味着,例如,在C#中我们不能string.Empty在以下情况下使用:
switch表格中的陈述case string.Empty:void M(string x = string.Empty) { }[SomeAttribute(string.Empty)]这对于众所周知的"宗教战争"是否影响是否使用string.Empty或"",请参阅" 在C#中,我应该使用string.Empty或String.Empty还是"来初始化字符串? ".
几年前,我Empty通过反射设置其他字符串实例来自娱自乐,看看BCL有多少部分由于它而开始表现奇怪.这是很多.并且Empty参考的变化似乎在应用程序的整个生命周期中持续存在.现在,有一天我试图重复那个小噱头,但后来使用的是.NET 4.5机器,我再也无法做到了.
(注意!如果您的计算机上安装了.NET 4.5,可能PowerShell仍然使用较旧版本的.NET,请尝试复制粘贴[String].GetField("Empty").SetValue($null, "Hello world!")到PowerShell中以查看更改此引用的一些效果.)
当我试图寻找原因时,我偶然发现了一个有趣的主题:" .NET 4.5 beta版本中FatalExecutionEngineError的原因是什么? ".在该问题的公认答案中,是否注意到通过版本4.0,System.String有一个静态构造函数.cctor,其中Empty设置了字段(在C#源中,当然可能只是一个字段初始化程序),而在4.5中没有静态构造函数存在.在这两个版本中,字段本身看起来都是一样的:
.field public …Run Code Online (Sandbox Code Playgroud) 我试图理解为什么string.Empty是readonly和不是const.我看过这篇帖子,但我不明白微软写的关于它的评论.正如Jon Skeet 在评论中所写的那样"我不知道 - 对我来说这没有多大意义,说实话......"
共享源公共语言基础结构2.0版本.string.cs位于sscli20\clr\src\bcl\system\string.cs中
// The Empty constant holds the empty string value.
//We need to call the String constructor so that the compiler doesn't mark this as a literal.
//Marking this as a literal would mean that it doesn't show up as a field which we can access
//from native.
public static readonly String Empty = "";
Run Code Online (Sandbox Code Playgroud)
我在这里看不到任何String构造函数调用,而且,它被标记为文字 - ""
有人可以用明文解释我,评论意味着什么,为什么string.Empty readonly不是const …
虽然我明白改变价值String.Empty会是一个坏主意,但我不明白为什么我不能这样做.
为了得到我的意思,请考虑以下课程:
public class SomeContext
{
static SomeContext(){}
public static readonly string Green = "Green";
public static readonly SomeContext Instance = new SomeContext();
private SomeContext(){}
public readonly string Blue = "Blue";
public static void PrintValues()
{
Console.WriteLine(new { Green, Instance.Blue, String.Empty }.ToString());
}
}
Run Code Online (Sandbox Code Playgroud)
我有一个小的控制台应用程序,试图操纵这三个只读字段.它可以成功地将蓝色和绿色变成粉红色,但是Empty保持不变:
SomeContext.PrintValues();
/// prints out : { Green = Green, Blue = Blue, Empty = }
typeof(SomeContext).GetField("Blue").SetValue(SomeContext.Instance, "Pink");
typeof(SomeContext).GetField("Green", BindingFlags.Public | BindingFlags.Static).SetValue(null, "Pink");
typeof(String).GetField("Empty", BindingFlags.Public | BindingFlags.Static).SetValue(null, "Pink");
SomeContext.PrintValues();
/// prints out : { …Run Code Online (Sandbox Code Playgroud) 此代码无效:
private void Foo(string optionalString = string.Empty)
{
// do foo.
}
Run Code Online (Sandbox Code Playgroud)
但是这段代码是:
private void Foo(string optionalString = "")
{
// do foo.
}
Run Code Online (Sandbox Code Playgroud)
为什么?因为string.Empty是只读字段,而不是常量,并且可选参数的缺省值必须是编译时常量.
那么,关于我的问题......(好吧,关心)
这就是我必须做的事情:
private const string emptyString = "";
private void Foo(string optionalString = emptyString)
{
// do foo.
if (!string.IsNullOrEmpty(optionalString))
// etc
}
Run Code Online (Sandbox Code Playgroud)
你们如何处理可选的字符串参数?
为什么它们不能使String.Empty成为编译时常量?
我在C#文章中多次使用原生和文字 "关键字".他们的意思是什么?
例子:
Empty常量保存空字符串值.我们需要调用String构造函数,以便编译器不会将其标记为 文字.将其标记为文字将意味着它不会显示为我们可以从本机访问的字段.
简单/原始类型
两种语言都支持许多内置类型,这些类型按值而不是通过引用进行复制和传递.Java将这些类型称为原始类型,而它们在C#中称为简单类型.简单/原始类型通常具有来自底层处理器体系结构的本机支持.
今天我在构造函数中创建了一个默认参数值.
public SomeClass (String something = String.Empty)
{
// ...
}
Run Code Online (Sandbox Code Playgroud)
编译器抱怨道.
"something"的默认参数值必须是编译时常量.
我的印象是String类上的Empty是编译时常量.
.field public static initonly string Empty
Run Code Online (Sandbox Code Playgroud)
我是否理解编译时常量的含义,还是我需要接受的更为古怪?
我正在改进我的代码并注意到在某些地方我有可选参数,其默认值为空字符串.我将其更改为类中的默认值为空字符串,猜猜是什么!显然,空引号和string.Empty.之间存在差异.什么鸭子?!(打字错误)
private void Khaboom(String parameter = "") { ... }
private void Bazinga(String parameter = String.Empty) { ... }
Run Code Online (Sandbox Code Playgroud)
谁能向我解释为什么不鸭Khaboom工作,同时Bazinga不?
错误消息引发了这样的错误:
'parameter'的默认参数值必须是编译时常量.
嗯...... 是的!
整个程序采用.net网络应用程序的Web形式:
namespace WebApplication1
{
public partial class WebForm1 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
string x = "";
string y = String.Empty;
}
}
}
Run Code Online (Sandbox Code Playgroud)
如果我构建应用程序,编译器会强调x,
赋值变量x,但从不使用它的值
对于y,我没有强调.为什么不?(VS 2008,.Net 3.5)
我经常使用String.Empty占位符,相当于"".所以我的问题,为什么不const喜欢String.Empty?他们编译相同.
// Good
private const string example = "";
// Bad
private const string example = String.Empty;
Run Code Online (Sandbox Code Playgroud)
是什么String.Empty让它无法与a一起使用const.
如果我键入以下内容:
public Response GetArticles(string Filter = String.Empty)
{
//Body
}
Run Code Online (Sandbox Code Playgroud)
Visual Studio给了我这个错误:
"Filter"的默认参数值必须是编译时常量
如果我改为String.Empty经典,""它就是固定的.
但我仍然对这个String.Empty及其行为的错误感到好奇.
c# ×12
.net ×8
string ×6
c#-4.0 ×2
.net-4.5 ×1
compile-time ×1
constants ×1
immutability ×1
keyword ×1
parameters ×1
readonly ×1
reflection ×1
variables ×1