积极答复者
c#值类型和引用类型存储值的相关问题

问题
答案
-
string 对象称为不可变的(只读),因为一旦创建了该对象,就不能修改该对象的值。看来似乎修改了,实际是string经过了特殊处理,每次改变值时都会建立一个新的string对象,变量会指向这个新的对象,而原来的还是指向原来的对象,所以不会改变。这也是string效率低下的原因,如果经常改变string的值则应该使用StringBuilder而不使用string
family as water- 已标记为答案 Mio_MiaoModerator 2010年12月29日 1:29
-
chinasnail 你好,
欢迎来到MSDN论坛!
之前Stone Z说的对。
在你给出的例子当中,我们单独来看关于string的那部分代码:
string str = "ab";
string str1 = str;
str = "abc";
str1 = ?在这里str1的值还是ab,因为string对象是不可变的,包括长度和其中任何字符都是不可以改变的。
虽然string是引用类型,但它是一种特殊的引用类型,每次使用string时,都要在内容中创建一个新的内存对象,即为该新对象分配新的,所以它的赋值可以按照值类型的赋值来处理。
希望以上的解释对你有所帮助。
Mio
Mio Miao[MSFT]
MSDN Community Support | Feedback to us
Get or Request Code Sample from Microsoft
Please remember to mark the replies as answers if they help and unmark them if they provide no help.
- 已标记为答案 Mio_MiaoModerator 2010年12月29日 1:29
-
dear
因为你摆的位置错误,你要str1改变
你可更改下列两行的顺序。
string str1 = str;
str = "abc";
改为
str = "abc";
string str1 = str;
或是
string str1 = str;
str1 = "abc";
这样str1就会变"abc"
若您是要藉由str改变str1是不可以的,因为他门是不同的执行个体,string 类别只要一被赋予新的值,他就会重新建立一个新的执行个体,对于动态变更字串string效率是叫差的,您可参考小弟写的效能比较
[Edit this entry.] [.NET] 動態處理字串 - StringBuilder 類別 與 String 類別的效能
http://www.dotblogs.com.tw/yc421206/archive/2010/10/26/18575.aspx
秘訣無它,唯勤而已 http://www.dotblogs.com.tw/yc421206/- 已标记为答案 Mio_MiaoModerator 2010年12月29日 1:29
-
我来说一点高级的吧,string 只是在正常情况下是不可变的 (immutable),但是,在某些情况下,它是可变的。
大家可以研究一下最高效的 string 反转代码。就知道了。
public unsafe void Reverse(string input)
{
int length = input.Length;
fixed (char* p = input)
{
int i = 0;
int j = input.Length - 1;
while (i < j)
{
char temp = *(p + i);
*(p + i) = *(p + j);
*(p + j) = temp;
i++;
j--;
}
}
}原理就是字符串的头和尾的字符对调。大家可以看到,返回值为 void,也就是直接用代码改变了输入的 string 参数。
Mark Zhou- 已建议为答案 Charles Shao 2010年12月28日 0:01
- 已标记为答案 Mio_MiaoModerator 2010年12月29日 1:30
-
我来说一点高级的吧,string 只是在正常情况下是不可变的 (immutable),但是,在某些情况下,它是可变的。
大家可以研究一下最高效的 string 反转代码。就知道了。
public unsafe void Reverse(string input)
{
int length = input.Length;
fixed (char* p = input)
{
int i = 0;
int j = input.Length - 1;
while (i < j)
{
char temp = *(p + i);
*(p + i) = *(p + j);
*(p + j) = temp;
i++;
j--;
}
}
}原理就是字符串的头和尾的字符对调。大家可以看到,返回值为 void,也就是直接用代码改变了输入的 string 参数。
Mark Zhou我觉得不应该这么做
不排除以后c#为了优化性能,使得相同内容的string指向同一个地址的char*。
而且这么做会破坏string的hash机制,如果string为了优化缓存了长字符串的hash值呢?或者这个string已经在hashset之类的容器之内呢。
immutable和mutable的string的这是一个选择。既然C#选择了前者,一定要遵循。
- 已标记为答案 Mio_MiaoModerator 2010年12月29日 1:30
全部回复
-
string 对象称为不可变的(只读),因为一旦创建了该对象,就不能修改该对象的值。看来似乎修改了,实际是string经过了特殊处理,每次改变值时都会建立一个新的string对象,变量会指向这个新的对象,而原来的还是指向原来的对象,所以不会改变。这也是string效率低下的原因,如果经常改变string的值则应该使用StringBuilder而不使用string
family as water- 已标记为答案 Mio_MiaoModerator 2010年12月29日 1:29
-
chinasnail 你好,
欢迎来到MSDN论坛!
之前Stone Z说的对。
在你给出的例子当中,我们单独来看关于string的那部分代码:
string str = "ab";
string str1 = str;
str = "abc";
str1 = ?在这里str1的值还是ab,因为string对象是不可变的,包括长度和其中任何字符都是不可以改变的。
虽然string是引用类型,但它是一种特殊的引用类型,每次使用string时,都要在内容中创建一个新的内存对象,即为该新对象分配新的,所以它的赋值可以按照值类型的赋值来处理。
希望以上的解释对你有所帮助。
Mio
Mio Miao[MSFT]
MSDN Community Support | Feedback to us
Get or Request Code Sample from Microsoft
Please remember to mark the replies as answers if they help and unmark them if they provide no help.
- 已标记为答案 Mio_MiaoModerator 2010年12月29日 1:29
-
dear
因为你摆的位置错误,你要str1改变
你可更改下列两行的顺序。
string str1 = str;
str = "abc";
改为
str = "abc";
string str1 = str;
或是
string str1 = str;
str1 = "abc";
这样str1就会变"abc"
若您是要藉由str改变str1是不可以的,因为他门是不同的执行个体,string 类别只要一被赋予新的值,他就会重新建立一个新的执行个体,对于动态变更字串string效率是叫差的,您可参考小弟写的效能比较
[Edit this entry.] [.NET] 動態處理字串 - StringBuilder 類別 與 String 類別的效能
http://www.dotblogs.com.tw/yc421206/archive/2010/10/26/18575.aspx
秘訣無它,唯勤而已 http://www.dotblogs.com.tw/yc421206/- 已标记为答案 Mio_MiaoModerator 2010年12月29日 1:29
-
我来说一点高级的吧,string 只是在正常情况下是不可变的 (immutable),但是,在某些情况下,它是可变的。
大家可以研究一下最高效的 string 反转代码。就知道了。
public unsafe void Reverse(string input)
{
int length = input.Length;
fixed (char* p = input)
{
int i = 0;
int j = input.Length - 1;
while (i < j)
{
char temp = *(p + i);
*(p + i) = *(p + j);
*(p + j) = temp;
i++;
j--;
}
}
}原理就是字符串的头和尾的字符对调。大家可以看到,返回值为 void,也就是直接用代码改变了输入的 string 参数。
Mark Zhou- 已建议为答案 Charles Shao 2010年12月28日 0:01
- 已标记为答案 Mio_MiaoModerator 2010年12月29日 1:30
-
我来说一点高级的吧,string 只是在正常情况下是不可变的 (immutable),但是,在某些情况下,它是可变的。
大家可以研究一下最高效的 string 反转代码。就知道了。
public unsafe void Reverse(string input)
{
int length = input.Length;
fixed (char* p = input)
{
int i = 0;
int j = input.Length - 1;
while (i < j)
{
char temp = *(p + i);
*(p + i) = *(p + j);
*(p + j) = temp;
i++;
j--;
}
}
}原理就是字符串的头和尾的字符对调。大家可以看到,返回值为 void,也就是直接用代码改变了输入的 string 参数。
Mark Zhou
dear mark听君一席话胜过万卷书
秘訣無它,唯勤而已 http://www.dotblogs.com.tw/yc421206/ -
我来说一点高级的吧,string 只是在正常情况下是不可变的 (immutable),但是,在某些情况下,它是可变的。
大家可以研究一下最高效的 string 反转代码。就知道了。
public unsafe void Reverse(string input)
{
int length = input.Length;
fixed (char* p = input)
{
int i = 0;
int j = input.Length - 1;
while (i < j)
{
char temp = *(p + i);
*(p + i) = *(p + j);
*(p + j) = temp;
i++;
j--;
}
}
}原理就是字符串的头和尾的字符对调。大家可以看到,返回值为 void,也就是直接用代码改变了输入的 string 参数。
Mark Zhou我觉得不应该这么做
不排除以后c#为了优化性能,使得相同内容的string指向同一个地址的char*。
而且这么做会破坏string的hash机制,如果string为了优化缓存了长字符串的hash值呢?或者这个string已经在hashset之类的容器之内呢。
immutable和mutable的string的这是一个选择。既然C#选择了前者,一定要遵循。
- 已标记为答案 Mio_MiaoModerator 2010年12月29日 1:30
-
string 的 immutable 仅仅体现在托管代码层面,当然,在所有基于托管代码的实现中,必须保证 string 的不可变性。
但在有些时候,比如,托管代码和非托管代码之间的交互,原生的 string 类型就必须被 fixed 之后再 pinned。这一点可以通过对 Interop 的代码进行 IL 反编译看到。这种情况下,要求托管 string 必须具备一个固定地址的指针 (fixed char*),否则无法支持其他非托管代码,如 C++ 的代码。
毫无疑问,在任何只有托管代码的实现中,请保持 string 不可变;在任何特殊需要,如核心算法和 Interop 时,请考虑使用 fixed char*。
楼上的 Charles Shao 的说法不是很准确,string 在设计时就是原生类型,是不可变类型t,只不过在某些时候可以让他可变。
Mark Zhou