这是一个及其常见的问题网上已经有关于这个问题的很多讨论但是我觉得都是不求甚解有一些还是在误导别人下面我来说下我对这三者的理解如有错误的地方请大家及时指正 一与stringEmpty我认为是一样的网上有一篇被转载了几十遍的文章是这样说的stringEmpty 不分配存储空间 分配一个长度为空的存储空间我认为这句话是错误并且含糊不清的 实际上Empty是string类中的一个静态的只读字段他的定义是这样的 public static readonly String Empty = ; 也就是说stringEmpty的内部实现是等于的 我要反驳stringEmpty 不分配存储空间 分配一个长度为空的存储空间这个观点首先stringEmpty与都会分配存储空间具体的说是都会在内存的栈和堆上分配存储空间 有一点先说明一下引用类型是将对象是实际数据保存在堆上 将对象在堆上的地址保存在栈上因此stringEmpty与都会在栈上保存一个地址这个地址占字节指向内存堆中的某个长度为的空间这个空间保存的是stringEmpty的实际值这个我可以用VS跟蹤下内存给大家演示 上图中的xe即是变量str在栈中存储的地址 对于请看下图 这个图的效果跟上图是一样的也就是说也是在栈上保存了一个地址 CLR会对字符串进行优化所以和stringEmpty也都会被优化 声明如下两个变量 string str=; string str=; str与str的引用会是相同的也就是str与str在栈上保存的地址上相同的请看下图 上图是str的地址 上图是str的地址 可见str于str的地址是相同的也就是说str会在堆上占用一个长度为的空间而str不会在堆上开辟新的空间 str于str在堆上共享同一空间 同理对于 string str=stringEmpty; string str= stringEmpty; str与str的地址也是相同的也是在内存堆上共享同一空间如下图 上图是str的地址 上图是str的地址 如果非要说与stringEmpty有什么不同的话我觉得是写法不一样stringEmpty看起来好看~!~是在优化方面稍有差别stringEmpty于c#对在语法级别的优化这点可以通过stringEmpty的内部实现看出来 public static readonly String Empty = ; 也就是说是通过CLR进行优化的CLR会维护一个字符串池以防在堆中创建重复的字符串而stringEmpty是一种c#语法级别的优化是在C#编译器将代码编译为IL(即MSIL)时进行了优化即所有对string类的静态字段Empty的访问都会被指向同一引用以节省内存空间 所以对的优化更依赖CLR 给大家看一下二者编译后的IL代码: string str=; 编译后如下 ldstr //从字符串池中取出一个(实际上取的是地址) stfld string ClassLibraryClass::str //将赋给str(实际上赋的是地址) string str=stringEmpty; 编译后如下 ldsfld string [mscorlib]SystemString::Empty//取得string类的静态字段Empty(实际上取的是地址) stfld string ClassLibraryClass::str//将Empty赋给str(实际上赋的是地址) 总结说了这么一大推我自己都觉得罗嗦而且初学者朋友可能会看不懂本人语文学的不好表达能力一般还请大家谅解下面我会挑要害来说 与stringEmpty在用法与性能上基本没区别stringEmpty是在语法级别对的优化 二stringEmpty与null的区别 因为stringEmpty与基本是一样的所以stringEmpty与null的区别也就代表了与null的区别 那就是stringEmpty会在堆上占用一个长度为的空间而null不会具体内容如下 string str=; string str=null; 如刚才所说str会在栈上保存一个地址这个地址占字节指向内存堆中的某个长度为的空间这个空间保存的是str的实际值 str同样会在栈上保存一个地址这个地址也占字节但是这个地址是没有明确指向的它哪也不指其内容为x如下图 |