1.当参数是值类型与引用类型的区别2.当参数string的时候与值类型的区别所有解答请看注释
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;namespace ConsoleCSharp
{
class classtest
{
public int test;
public string str;
public classtest()
{
test = 0;
str = "";
}
}
struct structtest
{
public int test;
public string str;
}
class Program
{
// ==与Equals一致,对值类型比较的是值相等,对于引用类型比较的是两地址是否相等
// 对于预定义的值类型,如果操作数的值相等,则相等运算符 (==) 返回真,否则,返回假。
// 对于除 string 类型以外的引用类型,如果两个操作数引用相同的对象,则 == 返回真。
// 对于 string 类型,== 将比较字符串的值。 // public static bool ReferenceEquals( object left, object right );
//这个函数就是判断两个引用类型对象是否指向同一个地址。有此说明后,就确定了它的使用范围,即只能对于引用类型操作。
//那么对于任何值类型数据操作,即使是与自身的判别,都会返回false。这主要因为在调用此函数的时候,值类型数据要进行装箱操作 static void Main(string[] args)
{
classtest ct = new classtest();
changeValue(ct);
classtest ct1 = ct;
Console.WriteLine("class : {0} {1} {2}", ct1 == ct, ct1.Equals(ct), object.ReferenceEquals(ct1, ct)); //True True
Console.WriteLine("{0} {1}", ct.test, ct.str);
// 首先在C#中传递方法参数缺省是“值拷贝”模式,也就是说对于值类型(ValueType)变量直接拷贝一份,
// 而对于引用类型则拷贝一个指向同一对象的引用副本传递给方法,因此即使不使用ref关键字,
// 我们也可以在方法内部改变该引用所指向对象的内部状态
structtest st = new structtest();
changeValue(st);
structtest st1 = st;
Console.WriteLine("struct : {0} {1} ", st1.Equals(st), object.ReferenceEquals(st1, st));
Console.WriteLine("{0} {1}", st.test, st.str); int i = 0;
int j = i;
Console.WriteLine("int : {0} {1} {2}", i == j, i.Equals(j), object.ReferenceEquals(i, j));
changeValue(i);
Console.WriteLine(i); string ss = "ss";
string ss2 = ss;
Console.WriteLine("string {0} {1} {2}", ss2 == ss, ss2.Equals(ss), object.ReferenceEquals(ss2, ss));
changeValue(ss);
Console.WriteLine(ss);
// string对象保存在堆上而不是堆栈上,是引用类型的,因而当把一个字符串变量赋给另一个字符串时,
// 会得到对内存中同一个字符串的两个引用.
//然后,修改其中一个字符串,注意这会创建一个完全新的string对象,而另一个字符串没改变!
}
static void changeValue(classtest t)
{
t.test += 100;
t.str += "class";
}
static void changeValue(int i)
{
i += 100;
}
static void changeValue(string i)
{
i += "string";
}
static void changeValue(structtest t)
{
t.test += 200;
t.str += "struct";
} }
}
欢迎大家拍砖,指出bug着得多分,只顶贴着得小分。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;namespace ConsoleCSharp
{
class classtest
{
public int test;
public string str;
public classtest()
{
test = 0;
str = "";
}
}
struct structtest
{
public int test;
public string str;
}
class Program
{
// ==与Equals一致,对值类型比较的是值相等,对于引用类型比较的是两地址是否相等
// 对于预定义的值类型,如果操作数的值相等,则相等运算符 (==) 返回真,否则,返回假。
// 对于除 string 类型以外的引用类型,如果两个操作数引用相同的对象,则 == 返回真。
// 对于 string 类型,== 将比较字符串的值。 // public static bool ReferenceEquals( object left, object right );
//这个函数就是判断两个引用类型对象是否指向同一个地址。有此说明后,就确定了它的使用范围,即只能对于引用类型操作。
//那么对于任何值类型数据操作,即使是与自身的判别,都会返回false。这主要因为在调用此函数的时候,值类型数据要进行装箱操作 static void Main(string[] args)
{
classtest ct = new classtest();
changeValue(ct);
classtest ct1 = ct;
Console.WriteLine("class : {0} {1} {2}", ct1 == ct, ct1.Equals(ct), object.ReferenceEquals(ct1, ct)); //True True
Console.WriteLine("{0} {1}", ct.test, ct.str);
// 首先在C#中传递方法参数缺省是“值拷贝”模式,也就是说对于值类型(ValueType)变量直接拷贝一份,
// 而对于引用类型则拷贝一个指向同一对象的引用副本传递给方法,因此即使不使用ref关键字,
// 我们也可以在方法内部改变该引用所指向对象的内部状态
structtest st = new structtest();
changeValue(st);
structtest st1 = st;
Console.WriteLine("struct : {0} {1} ", st1.Equals(st), object.ReferenceEquals(st1, st));
Console.WriteLine("{0} {1}", st.test, st.str); int i = 0;
int j = i;
Console.WriteLine("int : {0} {1} {2}", i == j, i.Equals(j), object.ReferenceEquals(i, j));
changeValue(i);
Console.WriteLine(i); string ss = "ss";
string ss2 = ss;
Console.WriteLine("string {0} {1} {2}", ss2 == ss, ss2.Equals(ss), object.ReferenceEquals(ss2, ss));
changeValue(ss);
Console.WriteLine(ss);
// string对象保存在堆上而不是堆栈上,是引用类型的,因而当把一个字符串变量赋给另一个字符串时,
// 会得到对内存中同一个字符串的两个引用.
//然后,修改其中一个字符串,注意这会创建一个完全新的string对象,而另一个字符串没改变!
}
static void changeValue(classtest t)
{
t.test += 100;
t.str += "class";
}
static void changeValue(int i)
{
i += 100;
}
static void changeValue(string i)
{
i += "string";
}
static void changeValue(structtest t)
{
t.test += 200;
t.str += "struct";
} }
}
欢迎大家拍砖,指出bug着得多分,只顶贴着得小分。
class : True True True
100 class
struct : True False
0
int : True True False
0
string True True True
ss
Press any key to continue . . .
1.当参数是值类型与引用类型的区别2.当参数string的时候与值类型的区别这两个我都想回答 无区别 , 原因是 "参数" 只用按引用 和值传递 的区别而要说区别 也是 值类型与引用类型的区别, 和"参数" 无关
所以string要单独考虑
你说的这些可以找时间写写。不难
string ss = "ss";
string ss2 = ss;
Console.WriteLine("string {0} {1} {2}", ss2 == ss, ss2.Equals(ss), object.ReferenceEquals(ss2, ss));
changeValue(ss);
Console.WriteLine(ss);
// string对象保存在堆上而不是堆栈上,是引用类型的,因而当把一个字符串变量赋给另一个字符串时,
// 会得到对内存中同一个字符串的两个引用.
//然后,修改其中一个字符串,注意这会创建一个完全新的string对象,而另一个字符串没改变!
static void changeValue(string i)
{
i += "string";//这句的本质就是i = i + "string";
//就是说:i + "string" 这个表达式计算出结果,
//存入临时地址,把地址传给i
//i整个都被改掉了
}
参数可以通过值和引用两种方式传递,参数的不同传递方式本质上就是“值传递和引用传递”的区别。个人理解,参数传递的特征:
(1)是发生在不同作用域之间的传递。
(2)ref 是参数专用修饰符,从字面上已指明是传址(by reference),所以是引用类型传递。除此之外属于共性:传值参数传递的是调用参数的一份拷贝,在传递过程完成之后,保留原值。
传址参数传递的是调用参数的内存地址,该参数在方法内外指向的是同一个存储位置。
所以虽然传递的是同一个引用地址 但是在堆中其实创建了另外一个副本了,所以即使是用ref引用也没有用
你们也在看本质论呀,我的书是C#3.0的 刚看到第9章 合式类型
string str="hello";
string s=str+"dd";
str和s不是同一个对象,也不指向同一个对象。clr对string做了很多优化
string str="hello";
str="hi";首先明确一下,string 是不可变的 ,可执行代码后会显示str="hi";从直观的感觉是 string 是不可变的 不成立,实质是怎样的呢以下为个人观点,仅供参考,欢迎指正,以免误导。string str="hello"; 做了以下几件事 ,首先从字符池中查找 "hello",没有找到 然后会在字符池中创建"hello",存储形式是值类型 存在栈上string str 是定义一个 string 类型的实例 ,存储形式是引用类型 存在堆上 指向的是 "hello" 所存储的地址。str="hi"; 做了什么呢 首先从字符池中查找 "hi",没有找到 在字符池中创建"hi" ,同时将 string 类型的实例 str 的指向 由指向"hello" 所存储的地址 转变成"hi" 所存储的地址字符池中的 "hello" 并没有改变
{
int length = strA.Length;
if (length != strB.Length) return false;
fixed(char* ap = strA) fixed(char* bp = strB)
{
char* a = ap;
char* b = bp; // unroll the loop
#if AMD64
// for AMD64 bit platform we unroll by 12 and
// check 3 qword at a time. This is less code
// than the 32 bit case and is shorter
// pathlength while (length >= 12)
{
if (*(long*)a != *(long*)b) break;
if (*(long*)(a+4) != *(long*)(b+4)) break;
if (*(long*)(a+8) != *(long*)(b+8)) break;
a += 12; b += 12; length -= 12;
}
#else
while (length >= 10)
{
if (*(int*)a != *(int*)b) break;
if (*(int*)(a+2) != *(int*)(b+2)) break;
if (*(int*)(a+4) != *(int*)(b+4)) break;
if (*(int*)(a+6) != *(int*)(b+6)) break;
if (*(int*)(a+8) != *(int*)(b+8)) break;
a += 10; b += 10; length -= 10;
}
#endif
// This depends on the fact that the String objects are
// always zero terminated and that the terminating zero is not included
// in the length. For odd string sizes, the last compare will include
// the zero terminator.
while (length > 0)
{
if (*(int*)a != *(int*)b) break;
a += 2; b += 2; length -= 2;
} return (length <= 0);
}
}
找到string的Equal比较函数代码,可以看出,是直接比较2个数组里面的值
个人观点还是字符串每次赋值都创建了一个新对象。
不应该存在字符串池。
通常来引用说不需要ref 就能通过方法改变其值 ,
但是字符串是不可变的
好像只有重新new了一个字符串,为其分配一个新的空间,
但这时方法外字符串的引用和方法里的不一样,所以执行方法后值没有改变 , 加了ref 的话同上也是新建了一个,但是引用一样了,所以改变了
{
public string s = null;
public int i = 0;
}
public void run()
{
test instance = new test();
instance.s = "first";
instance.i = 1;
callByValue(instance);
}
public void callByValue(test t)
{
t.s = "changed";
t.i = 2;
} 本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/vrhero/archive/2010/01/09/5166278.aspx这段代码就是广泛会被误认为按引用传递实际上是按值传递的参数传递方式...它的执行结果非常明显,参数引用类型test的实例instance的成员s和i一定会被更改,所以看起来它似乎确实是按引用传递的...但是,错的!这个参数传递的是该参数实例的一个副本!引用类型实例的副本是什么呢?就是这个instance的引用的副本...也就是说,这个时候在栈上,原来的instance的引用还在,传递给callByValue方法的参数t是栈上instance的引用的copy...这个copy引用指向托管堆上instance值的地址,所以一改俱改...所以表象似乎一样,但和C/C++传递指针的方式本质是差别巨大的...
本文来自CSDN博客,转载请标明出处:http://blog.csdn.net/vrhero/archive/2010/01/09/5166278.aspx