.net知识和学习方法系列(二十二)CLR-方法的参数out,ref

简介:
因为数值类型的分类是值类型和引用类型,所以方法的参数也有这两种类型。
值类型参数:
static void Main()
{
  int i=1;
Mehtod(i);
}
static void Method(int s)
{
  s=200;
}
如果方法的参数是值类型,调用者Main传递给被调用方法Method的是一个值类型的副本,即i的一个副本,i与方法Method中的s值相同,但一旦调用完毕两都就没有关系了。
引用类型:
static void Main()
{
  int[] arri=new int[]{1};
Method(arri);
}
static void Method(int[] arrs)
{
  Arrs[0]=200;
}
引用类型作为方法的参数时,调用者传递的是引用(与指针类似),即把arri数组的引用传给Method方法,这里只是把引用传递给方法,而非副本,这点就使在Main中的arri与在Method中的arrs引用的是同一个对象,在两个方法的任何地方使之改变都会影响另一个方法的数据的。
简单的说,值类型参数传递副本,引用类型参数传递引用。
 
接下来说说ref和out作为参数
先看一下下面的代码,
        static void F1(ref int i)
        {
            i = 100;
        }
        static void F2(out int i)
        {
            i = 100;
        }
看看这两个方法对应的IL
.method private hidebysig static void F1(int32& i) cil managed
{
 // 代码大小       6 (0x6)
 .maxstack 8
 IL_0000: nop
 IL_0001: ldarg.0
 IL_0002: ldc.i4.s   100
 IL_0004: stind.i4
 IL_0005: ret
} // end of method Program::F1
 
.method private hidebysig static void F2([out] int32& i) cil managed
{
 //  代码大小        6 (0x6)
 .maxstack 8
 IL_0000: nop
 IL_0001: ldarg.0
 IL_0002: ldc.i4.s   100
 IL_0004: stind.i4
 IL_0005: ret
} // end of method Program::F2
我们通过生成的中间语言看到,这两个方法只有一个差别就是在F2的参数中多了一个[out],方法体中是全部一样的。其实对于CLR来说,这两个关键字是没有区别的,都是能以引用类型的方式来操作参数。
为什么在C#中要区分out和ref呢?主要是因为out是输入参数,只希望它从方法内得到值返回,而ref即要把参数带到方法,也可以带出参数,就是说这只是C#编辑器的愿望,所以在C#中是区别的,但在CLR在运得exe的元数据是不区另的(因为托管理程序是两次编译)。
 
下面通过另一个方法看看ref和out
static void F1(ref int i)
        {
            i = 100;
        }
        static void F1(int i)
        {
            i = 100;
        }
上面的代码放在一个类中是能通过编译的,因为构成了重载
我们看以看一下普通方法的IL
.method private hidebysig static void F1(int32 i) cil managed
{
 //  代码大小        6 (0x6)
 .maxstack 8
 IL_0000: nop
 IL_0001: ldc.i4.s   100
 IL_0003: starg.s    i
 IL_0005: ret
} // end of method Program::F1
最明显的差别是参数普通方法是 int32 i ,而加ref,out的是int32& i,参数的不同使重载成为可以。但ref和out,如果参数类型个数相同的话刚形不成重载,因为它们是相同的,不充许出现相同方法(方法的签名)。
















本文转自桂素伟51CTO博客,原文链接:http://blog.51cto.com/axzxs/149957 ,如需转载请自行联系原作者

相关文章
|
28天前
|
API C++ Windows
Visual C++运行库、.NET Framework和DirectX运行库的作用及常见问题解决方案,涵盖MSVCP140.dll丢失、0xc000007b错误等典型故障的修复方法
本文介绍Visual C++运行库、.NET Framework和DirectX运行库的作用及常见问题解决方案,涵盖MSVCP140.dll丢失、0xc000007b错误等典型故障的修复方法,提供官方下载链接与系统修复工具使用指南。
423 2
|
1月前
|
人工智能 API 数据库
Semantic Kernel .NET 架构学习指南
本指南系统解析微软Semantic Kernel .NET架构,涵盖核心组件、设计模式与源码结构,结合实战路径与调试技巧,助你从入门到贡献开源,掌握AI编排开发全栈技能。
167 2
|
12月前
|
Java 物联网 C#
C#/.NET/.NET Core学习路线集合,学习不迷路!
C#/.NET/.NET Core学习路线集合,学习不迷路!
461 0
|
SQL 缓存 开发框架
分享一个 .NET EF6 应用二级缓存提高性能的方法
分享一个 .NET EF6 应用二级缓存提高性能的方法
160 0
|
缓存 NoSQL Java
【Azure Redis 缓存 Azure Cache For Redis】Redis出现 java.net.SocketTimeoutException: Read timed out 异常
【Azure Redis 缓存 Azure Cache For Redis】Redis出现 java.net.SocketTimeoutException: Read timed out 异常
181 5
|
开发框架 缓存 算法
开源且实用的C#/.NET编程技巧练习宝库(学习,工作,实践干货)
开源且实用的C#/.NET编程技巧练习宝库(学习,工作,实践干货)
802 0
|
开发框架 监控 .NET
|
程序员 数据库
分享 2 个 .NET EF 6 只更新某些字段的方法
分享 2 个 .NET EF 6 只更新某些字段的方法
301 0
|
数据库
分享一个 .NET EF 6 扩展 Where 的方法
分享一个 .NET EF 6 扩展 Where 的方法
149 0

热门文章

最新文章