积极答复者
大家来看看,这道题答案是几??

问题
-
class Class1 {
private string str = "class1.str";
private int i = 0;
static void StringConvert(string str) {
str = "string being converted.";
}
static void StringConvert(Class1 c) {
c.str = "string being converted.";
}
static void Add(int i) {
i++;
}
static void AddWithRef(ref int i) {
i++;
}
static void Main() {
int i1 = 10;
int i2 = 20;
string str = "str";
Class1 c = new Class1();
Add(i1);
AddWithRef(ref i2);
Add(c.i);
StringConvert(str);
StringConvert(c);
Console.WriteLine(i1);
Console.WriteLine(i2);
Console.WriteLine(c.i);
Console.WriteLine(str);
Console.WriteLine(c.str);
Console.Read();
}
}
输出答案是多少呢??我不懂为什么,希望大家给解释一下!!
谢谢!!
答案
-
哦!原来是这里不明白啊!
我给你解释一下,字符串的确是引用类型的,但是这个引用类型很特殊,他在行为上和值类型很类似,这实际上也是微软的设计目的,他的目的就是想让我们像使用值类型那样使用string类型!因为从一般常识来认识String就应该是值类型的!
上面说的希望你能够理解,下面我针对这个问题做个解释:
String就是引用类型的,但是很特殊,因为一旦字符串的值被修改,系统就会自动创建一个新的字符串对象,并使原来的字符串引用指向这个新创建的对象!
比如:
string s1="aaa";
string s2=s1; //这时s1和s2都是“aaa"
s2="bbb"; //这时s2的值是"bbb",因为一旦字符串的值被修改,系统就会自动创建一个新的字符串对象,并使原来的字符串引用指向这个新创建的对象,而这时s1的值还是"aaa",这个行为和值类型很类似,实际上string绝对是引用类型!
周雪峰- 已标记为答案 痴迷.Net 2009年6月20日 0:31
-
也许是我没有说清楚,这两个i我知道是这么回事,主要在两句话上面了,
Console.WriteLine(str);
Console.WriteLine(c.str);
为什么不一样呢??
字符串不是引用类型么??
这个大家再解释一下!!
谢谢!!
hi,
自己查询资料吧。我只能从IL来分析一下了,自己运行了一下,也做了几次修改。也算是我也学习了。我对你字符串部分的代码做了整理,分别是三个方法:
1. static void StringConvert(string str)
{
str = "string being converted.";
}
2. static void StringConvert(ref string str)
{
str = "string being converted.";
}
3. static void StringConvert(Class1 c)
{
c.strFeild = "string being converted.";
}
,然后反汇编看IL:
.method private hidebysig static void StringConvert(string str) cil managed
{
// 代码大小 9 (0x9)
.maxstack 8
IL_0000: nop//如果修补操作码,则填充空间。尽管可能消耗处理周期,但未执行任何有意义的操作。
IL_0001: ldstr "string being converted."//推送对元数据中存储的字符串的新对象引用。
IL_0006: starg.s str//从堆栈中弹出位于顶部的值并将其存储在参数槽 num 中。
IL_0008: ret//从当前方法返回,并将返回值(如果存在)从调用方的计算堆栈推送到被调用方的计算堆栈上。
} // end of method Class1::StringConvert
.method private hidebysig static void StringConvert(class Fibonacci.Class1 c) cil managed
{
// 代码大小 13 (0xd)
.maxstack 8
IL_0000: nop
IL_0001: ldarg.0//将索引为 0 的参数值推送到堆栈上。
IL_0002: ldstr "string being converted."//推送对元数据中存储的字符串的新对象引用。
IL_0007: stfld string Fibonacci.Class1::str//用新值替换在对象引用或指针的字段中存储的值。
IL_000c: ret//从当前方法返回,并将返回值(如果存在)从调用方的计算堆栈推送到被调用方的计算堆栈上。
} // end of method Class1::StringConvert
.method private hidebysig static void StringConvert(string& str) cil managed
{
// 代码大小 9 (0x9)
.maxstack 8
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldstr "string being converted."
IL_0007: stind.ref//存储所提供地址处的对象引用值。
IL_0008: ret
} // end of method Class1::StringConvert
你可以看出实际你的方法1. static void StringConvert(string str),IL代码可以看出是没有创建或者对原来的引用修改的。所以内容没变。
2. static void StringConvert(ref string str),IL代码可以看出用新值替换在对象引用或指针的字段中存储的值。
3. static void StringConvert(Class1 c),//操作的是原来对象引用值。所以做了修改。
以上是个人整理的,算是与你一起交流吧。此外其实字符串是个复杂的引用对象,深入学习的话还会涉及到.NET平台的底层机制,如字符串驻留等问题。
你在自己学习的时候,自己查资料最好,找些权威的资料。国内的学习风气不如国外。灌水的太多了...
Frank.Xu Lei--谦卑若愚,好学若饥
专注于.NET平台下分布式应用系统开发和企业应用系统集成
Focus on Distributed Applications Development and EAI based on .NET
老徐的博客:http://frank_xl.cnblogs.com- 已标记为答案 痴迷.Net 2009年6月20日 0:31
全部回复
-
答案你运行就知道啦,主要是要了解函数传值和地址的区别
http://feiyun0112.cnblogs.com/ -
哦!原来是这里不明白啊!
我给你解释一下,字符串的确是引用类型的,但是这个引用类型很特殊,他在行为上和值类型很类似,这实际上也是微软的设计目的,他的目的就是想让我们像使用值类型那样使用string类型!因为从一般常识来认识String就应该是值类型的!
上面说的希望你能够理解,下面我针对这个问题做个解释:
String就是引用类型的,但是很特殊,因为一旦字符串的值被修改,系统就会自动创建一个新的字符串对象,并使原来的字符串引用指向这个新创建的对象!
比如:
string s1="aaa";
string s2=s1; //这时s1和s2都是“aaa"
s2="bbb"; //这时s2的值是"bbb",因为一旦字符串的值被修改,系统就会自动创建一个新的字符串对象,并使原来的字符串引用指向这个新创建的对象,而这时s1的值还是"aaa",这个行为和值类型很类似,实际上string绝对是引用类型!
周雪峰- 已标记为答案 痴迷.Net 2009年6月20日 0:31
-
也许是我没有说清楚,这两个i我知道是这么回事,主要在两句话上面了,
Console.WriteLine(str);
Console.WriteLine(c.str);
为什么不一样呢??
字符串不是引用类型么??
这个大家再解释一下!!
谢谢!!
hi,
自己查询资料吧。我只能从IL来分析一下了,自己运行了一下,也做了几次修改。也算是我也学习了。我对你字符串部分的代码做了整理,分别是三个方法:
1. static void StringConvert(string str)
{
str = "string being converted.";
}
2. static void StringConvert(ref string str)
{
str = "string being converted.";
}
3. static void StringConvert(Class1 c)
{
c.strFeild = "string being converted.";
}
,然后反汇编看IL:
.method private hidebysig static void StringConvert(string str) cil managed
{
// 代码大小 9 (0x9)
.maxstack 8
IL_0000: nop//如果修补操作码,则填充空间。尽管可能消耗处理周期,但未执行任何有意义的操作。
IL_0001: ldstr "string being converted."//推送对元数据中存储的字符串的新对象引用。
IL_0006: starg.s str//从堆栈中弹出位于顶部的值并将其存储在参数槽 num 中。
IL_0008: ret//从当前方法返回,并将返回值(如果存在)从调用方的计算堆栈推送到被调用方的计算堆栈上。
} // end of method Class1::StringConvert
.method private hidebysig static void StringConvert(class Fibonacci.Class1 c) cil managed
{
// 代码大小 13 (0xd)
.maxstack 8
IL_0000: nop
IL_0001: ldarg.0//将索引为 0 的参数值推送到堆栈上。
IL_0002: ldstr "string being converted."//推送对元数据中存储的字符串的新对象引用。
IL_0007: stfld string Fibonacci.Class1::str//用新值替换在对象引用或指针的字段中存储的值。
IL_000c: ret//从当前方法返回,并将返回值(如果存在)从调用方的计算堆栈推送到被调用方的计算堆栈上。
} // end of method Class1::StringConvert
.method private hidebysig static void StringConvert(string& str) cil managed
{
// 代码大小 9 (0x9)
.maxstack 8
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldstr "string being converted."
IL_0007: stind.ref//存储所提供地址处的对象引用值。
IL_0008: ret
} // end of method Class1::StringConvert
你可以看出实际你的方法1. static void StringConvert(string str),IL代码可以看出是没有创建或者对原来的引用修改的。所以内容没变。
2. static void StringConvert(ref string str),IL代码可以看出用新值替换在对象引用或指针的字段中存储的值。
3. static void StringConvert(Class1 c),//操作的是原来对象引用值。所以做了修改。
以上是个人整理的,算是与你一起交流吧。此外其实字符串是个复杂的引用对象,深入学习的话还会涉及到.NET平台的底层机制,如字符串驻留等问题。
你在自己学习的时候,自己查资料最好,找些权威的资料。国内的学习风气不如国外。灌水的太多了...
Frank.Xu Lei--谦卑若愚,好学若饥
专注于.NET平台下分布式应用系统开发和企业应用系统集成
Focus on Distributed Applications Development and EAI based on .NET
老徐的博客:http://frank_xl.cnblogs.com- 已标记为答案 痴迷.Net 2009年6月20日 0:31