上述&QUOT混乱注释的含义;&的String.Empty QUOT;在.NET / BCL源? [英] Meaning of confusing comment above "string.Empty" in .NET/BCL source?

查看:328
本文介绍了上述&QUOT混乱注释的含义;&的String.Empty QUOT;在.NET / BCL源?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图理解为什么的String.Empty 只读,而不是常量。我看到的帖子,但我不明白的评论微软写一下吧。由于乔恩斯基特在评论中写道我不知道 - 它并没有多大意义,我,说实话......



共享源代码共同语言基础设施2.0发行。 string.cs是sscli20\clr\src\bcl\system\string.cs

  //的空不变持有空字符串值。 
//我们需要调用String构造,这样编译器不标记此为文字。
//标记此为文字将意味着它不会显示为,我们可以从本地访问
//一个字段。
公共静态只读字符串空=;

我无法在这里看到任何字符串构造函数的调用,而且,它被标记为文字 -



有人能请解释一下我的纯文本,什么是评论的意思是,为什么的String.Empty 只读,而不是常量






更新:结果



:埃里克利珀
通过现在删除答案评论

我问C#老前辈在午餐这个之一,为什么这个决定是他没有具体召回,但推测,它有一些东西做实习。



解决方案

的重要组成部分,是不是在这个类中发生,但是会发生什么,当另一个类用途(及链接)它。让我用一个例子说明:



假设你有一个包含类声明

 公共静态const int的SOME_ERROR_CODE = 0×10; 
公共静态只读INT SOME_OTHER_ERROR_CODE = 0x20的;

和其他类消费这如

 公众诠释TryFoo(){
尝试{富();}
赶上(抛出:InvalidParameterException){返回SOME_ERROR_CODE;}
赶上(例外){返回SOME_OTHER_ERROR_CODE ;}
返回0x00;
}

您编译类成Assembly2.dll,并将其链接对Assembly1.dll,正如所料,你的方法将返回为0x10无效参数,0x20的其他错误,为0x00上的成功。



特别是,如果你创建一个包含类似Assembly3.exe

  INT ERRORCODE = TryFoo(); 
如果(ERRORCODE == SOME_ERROR_CODE)巴();
,否则如果(ERRORCODE == SOME_OTHER_ERROR_CODE)巴兹();



如预期它将工作

现在,如果你得到Assembly1.dll的新版本,有

 公共const int的SOME_ERROR_CODE = 0×11; 
公共只读INT SOME_OTHER_ERROR_CODE = 0×21;

如果你重新编译Assembly3.exe和反对新Assembly1.dll不变Assembly2.dll链接的最后一个片段,它将停止为预期工作:



巴()将不会被正确调用:Assembly2.dll回忆文字为0x20,这是不一样的文字为0x21的Assembly3。 exe文件读出Assembly1.dll的



巴兹()将被正确调用:两个Assembly2.dll和Assembly3.exe指称为SOME_OTHER_ERROR_CODE符号引用,这是在两种。一个常量

在短>创建一个 LITERAL ,一个只读创建一个符号引用



文本是内部的框架,并且可以不被编组,因此所使用的本机代码。



所以

 公共静态只读字符串空=; 



创建一个符号引用(来拆分时刻通过向字符串cosntuctor通话首次使用),即可以被整理的这样,从本地使用,而

 公共静态常量空字符串=; 



将创建一个文字,这是不能。


I'm trying to understand why string.Empty is readonly and not a const. I saw this Post but I don't understand the comment Microsoft wrote about it. As Jon Skeet wrote in a comment "I don't know - it doesn't make much sense to me, to be honest..."

Shared Source Common Language Infrastructure 2.0 Release. string.cs is in 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 = ""; 

I can't see here any String constructor call and furthermore, it's marked as literal - ""

Can someone please explain me in plain text, What does the comment mean and why is string.Empty readonly and not a const?


Update:
Eric Lippert commented on by now a deleted answer:

I asked one of the C# old-timers over lunch about this and he did not recall specifically why this decision was made, but conjectured that it had something to do with interning.

解决方案

The important part is not what happens IN this class, but what happens, when another class uses (and links to) it. Let me explain with another example:

Assume you have a Assembly1.dll containing a class declaring

public static const int SOME_ERROR_CODE=0x10;
public static readonly int SOME_OTHER_ERROR_CODE=0x20;

and another class consuming this e.g.

public int TryFoo() {
    try {foo();}
    catch (InvalidParameterException) {return SOME_ERROR_CODE;}
    catch (Exception) { return SOME_OTHER_ERROR_CODE;}
    return 0x00;
}

You compile your class into Assembly2.dll and link it against Assembly1.dll, as expected, your method will return 0x10 on invalid parameters, 0x20 on other errors, 0x00 on success.

Especially, if you create Assembly3.exe containing something like

int errorcode=TryFoo();
if (errorcode==SOME_ERROR_CODE) bar();
else if (errorcode==SOME_OTHER_ERROR_CODE) baz();

It will work as expected (After being linked against Assembly1.dll and Assembly2.dll)

Now if you get a new version of Assembly1.dll, that has

public const int SOME_ERROR_CODE=0x11;
public readonly int SOME_OTHER_ERROR_CODE=0x21;

If you recompile Assembly3.exe and link the last fragment against new Assembly1.dll and unchanged Assembly2.dll, it will stop working as expected:

bar() will NOT be called correctly: Assembly2.dll remembers the LITERAL 0x20, which is not the same literal 0x21 that Assembly3.exe reads out of Assembly1.dll

baz() will be called correctly: Both Assembly2.dll and Assembly3.exe refer to the SYMBOL REFERENCE called SOME_OTHER_ERROR_CODE, which is in both cases resolved by the current version of Assembly1.dll, thus in both cases is 0x21.

In Short: a const creates a LITERAL, a readonly creates a SYMBOL REFERENCE.

LITERALS are internal to the framework and can not be marshalled and thus used by native code.

So

public static readonly String Empty = ""; 

creates a symbol reference (resovled at time of first use by a call to the String cosntuctor), that can be marshalled an thus used from native, while

public static const String Empty = ""; 

would create a literal, that can't.

这篇关于上述&QUOT混乱注释的含义;&的String.Empty QUOT;在.NET / BCL源?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆