理解C#中参数
2016-09-29 13:51
155 查看
岁末了 正好有机会说说C#中的ref,Out与参数传递的关系。
第一次写技术博客,写的不好,多提意见。
---------------------------------------------------------------------分割线--------------------------------------------------
分割线上面是2014年提的笔,现在是2016年收的尾!
没有准备我就随便写了!
C#中数据类型分值类型和引用类型,值类型变量保存的变量的值、引用类型保存的是变量的地址。
C#中函数的参数都是按值类型传递的,除非使用了ref 或者out。
先证明函数的参数是按值类型传递的:
看下面的例子
public void f1(int a)
{
a=123;
}
int b=111;
f1(b);
console.write(b);//111
上面调用函数f1时候过程是实参b给形参a赋值,a和b是两个互不影响的变量。这个比较容易理解。下面再看引用类型的案例
public void f2(List<int> ll)
{
ll.add(2);
}
List<int> l=new List<int>();
l.add(1);
f2(l);
console.write(l.count);//2
如果参数是按值类型传递的那为什么会输出2呢?因为引用类型变量名称保存的是值的值。
List<int> l=new List<int>();//这句话实际上在内存中开辟了2块存储空间,一个是l,另一块是l的值指向的地址
当调用f2的时候实参l给形参ll赋值,按值类型赋值,l的值赋给ll,此时ll的值也是上面new出来的地址,此时实参l和形参ll都是指向的同一个内存空间,所以在f2中对ll操作的结果会影响到l。下面讲string类型的
public void f3(string s)
{
s="def";
}
string str="abc";
f3(str)
console.write(str)//abc
咦!为什么是abc?如果按照刚刚讲的应该输出def才对啊!原因是这样的 在C#中string类型是不可变的(为什么说string类型是不可变的类型?我理解的是string s="abc";实际上也是string s=new string(new char[]{'a','b','c'});含义是在内存总开辟了一块空间保存abc,然后把这块空间的地址赋给变量s。)
这里的str 给s赋值,也是按照值类型进行赋值,赋值之后str和s同时指向abc,关键在于在函数f3中s="def";这一句话也就是s=new string(new char[]{'d','e','f'});解释在内存中开辟了一段空间存储def 然后把这段空间的地址赋给s。此时str 和s已经发生了质变,str还是原来的str,s已经不是原来的s了!
下面代码可以查看变量的地址
static void Main(string[] args)
{
unsafe
{
string str = "abc";
fixed (char* p = str)
{
Console.WriteLine("字符串地址= 0x{0:x}", (int)p);
}
f3(str);
fixed (char* p = str)
{
Console.WriteLine("字符串地址= 0x{0:x}", (int)p);
}
}
string ss = new string("asdf");
Console.ReadKey();
}
public static void f3(string s)
{
unsafe
{
fixed (char* p = s)
{
Console.WriteLine("参数赋值前字符串地址= 0x{0:x}", (int)p);
}
s = "def";
fixed (char* p = s)
{
Console.WriteLine("参数赋值后字符串地址= 0x{0:x}", (int)p);
}
}
}
再来说说ref和out
其实他们很简单理解ref 和out都是强制把参数以引用类型传递!具体可以自己写个例子自测。最后附图一张
第一次写技术博客,写的不好,多提意见。
---------------------------------------------------------------------分割线--------------------------------------------------
分割线上面是2014年提的笔,现在是2016年收的尾!
没有准备我就随便写了!
C#中数据类型分值类型和引用类型,值类型变量保存的变量的值、引用类型保存的是变量的地址。
C#中函数的参数都是按值类型传递的,除非使用了ref 或者out。
先证明函数的参数是按值类型传递的:
看下面的例子
public void f1(int a)
{
a=123;
}
int b=111;
f1(b);
console.write(b);//111
上面调用函数f1时候过程是实参b给形参a赋值,a和b是两个互不影响的变量。这个比较容易理解。下面再看引用类型的案例
public void f2(List<int> ll)
{
ll.add(2);
}
List<int> l=new List<int>();
l.add(1);
f2(l);
console.write(l.count);//2
如果参数是按值类型传递的那为什么会输出2呢?因为引用类型变量名称保存的是值的值。
List<int> l=new List<int>();//这句话实际上在内存中开辟了2块存储空间,一个是l,另一块是l的值指向的地址
当调用f2的时候实参l给形参ll赋值,按值类型赋值,l的值赋给ll,此时ll的值也是上面new出来的地址,此时实参l和形参ll都是指向的同一个内存空间,所以在f2中对ll操作的结果会影响到l。下面讲string类型的
public void f3(string s)
{
s="def";
}
string str="abc";
f3(str)
console.write(str)//abc
咦!为什么是abc?如果按照刚刚讲的应该输出def才对啊!原因是这样的 在C#中string类型是不可变的(为什么说string类型是不可变的类型?我理解的是string s="abc";实际上也是string s=new string(new char[]{'a','b','c'});含义是在内存总开辟了一块空间保存abc,然后把这块空间的地址赋给变量s。)
这里的str 给s赋值,也是按照值类型进行赋值,赋值之后str和s同时指向abc,关键在于在函数f3中s="def";这一句话也就是s=new string(new char[]{'d','e','f'});解释在内存中开辟了一段空间存储def 然后把这段空间的地址赋给s。此时str 和s已经发生了质变,str还是原来的str,s已经不是原来的s了!
下面代码可以查看变量的地址
static void Main(string[] args)
{
unsafe
{
string str = "abc";
fixed (char* p = str)
{
Console.WriteLine("字符串地址= 0x{0:x}", (int)p);
}
f3(str);
fixed (char* p = str)
{
Console.WriteLine("字符串地址= 0x{0:x}", (int)p);
}
}
string ss = new string("asdf");
Console.ReadKey();
}
public static void f3(string s)
{
unsafe
{
fixed (char* p = s)
{
Console.WriteLine("参数赋值前字符串地址= 0x{0:x}", (int)p);
}
s = "def";
fixed (char* p = s)
{
Console.WriteLine("参数赋值后字符串地址= 0x{0:x}", (int)p);
}
}
}
再来说说ref和out
其实他们很简单理解ref 和out都是强制把参数以引用类型传递!具体可以自己写个例子自测。最后附图一张
相关文章推荐
- 关于C#中ref与out参数的理解
- 深入理解C#之 参数传递 ref out params【转】
- C#中有关于:按 值 和 引用 传递参数 的理解
- 深入理解C#之 参数传递 ref out params
- 深入理解 c# 第五章 使用了忽略参数的匿名方法来订阅事件
- c#学习笔记之十 socket编程的listen()方法参数的理解,即backlog
- 深入理解C#之 参数传递 ref out params
- 理解C#中参数的值和引用以及传递结构和类引用的区别
- C# static void Main(String[] args) 中参数String[] args 的理解
- 我理解c#(一): 参数传递和变量复制之间的关系
- C# 参数传递、引用传递的一些个人理解
- c#中ref和out参数使用时需要注意的问题
- 理解C#中的string类型
- 编程访问带有varbinrany参数的存储过程(C#与ado版)
- 带输出参数的存储过程的使用及在C#中调用问题
- 对面向对象,VC,C#的理解
- 使用未公开关键字在 C# 中导入外部 printf 等参数数量可变函数 [1] CLR 支持
- 带输出参数的存储过程的使用及在C#中调用问题
- HOW TO:使用 ADO.NET 和 Visual C# .NET 调用带参数的存储过程
- 深入理解C#编程中的组件-事件-委托