参数传递

C#中有四种参数类型:值类型,Ref参数,Out参数,params参数。默认参数都是以传值方式传递,这意味着方法中的变量会在内存中被分配新的存储空间,并赋值。对于引用类型,这种传值意味着传递的是实例对象在栈中的地址。

void Foo (StringBuilder x)
{
x = null;
} ... StringBuilder y = new StringBuilder();
y.Append ("hello");
Foo (y);
Console.WriteLine (y==null);

代码中的y不会被改变。反之,下面的代码会输出“hello world”。(注意上面赋值的概念,如果变量存在一组子成员变量,现在两个变量都指向了同一片子成员变量,那么子成员变量的变化就会影响到两个变量)

void Foo (StringBuilder x)
{
x.Append (" world");
} ... StringBuilder y = new StringBuilder();
y.Append ("hello");
Foo (y);
Console.WriteLine (y);

如果将参数传递方式修改为Ref,那么上面的y就会被置为null,因为传递的是变量本身而非地址。进入方法的范围时,不会再分配新的存储空间,引用被修改,栈中的地址不再指向已分配的空间。

关于Using

使用Using语句块时,可以再Using语句内定义变量,也可以在其外部定义变量。但是如下这种写法在C#中会报错:Cannot pass 'TheInt' as a ref or out argument because it is a 'using variable'

public class DisposableInt : IDisposable
{
private int? _Value; public int? MyInt
{
get { return _Value; }
set { _Value = value; }
} public DisposableInt(int InitialValue)
{
_Value = InitialValue;
} public void Dispose()
{
_Value = null;
}
} public class TestAnInt
{
private void AddOne(ref DisposableInt IntVal)
{
IntVal.MyInt++;
} public void TestIt()
{
DisposableInt TheInt;
using (TheInt = new DisposableInt())
{
Console.WriteLine(String.Format("Int Value: {0}", TheInt.MyInt));
AddOne(ref TheInt);
Console.WriteLine(String.Format("Int Value + 1: {0}", TheInt.MyInt));
}
}
}

在Using语句内声明的变量全部是只读变量,这意味着在Using的语句块内不允许更改该对象的引用关系(例如,尝试赋值为null会报错)。因此,如果在此范围内使用ref或者out时会抛出编译器错误。在VB.NET中,不会直接抛出错误,但是会出现TheInt不会被修改的现象。原因在于以上的代码会被编译为(部分代码省略):

    public void TestIt()
{
DisposableInt TheInt =new DisposableInt();
DisposableInt TheInt2 = TheInt;
try
{
AddOne(ref TheInt2 );
}
finally
{
}
}

看到一个新的对象代替目标对象进入方法,原有的对象不会被修改。如果在AddOne的范围内出现引用被修改的情况,TheInt和TheInt2的参照关系会被修改。此时,在AddOne之后使用的TheInt实际上已经被编译器自动优化为TheInt2。

为了使用Using,可以讲代码修改为如下,此时TheInt不再是只读变量,就不会遇到此类问题:

DisposableInt theInt = new DisposableInt();
using (theInt)
{
AddOne(ref theInt);
}

最新文章

  1. getSupportFragmentManager要用在FragmentActivity及其子类中
  2. Java源文件编译成功但是运行时加载不到文件
  3. [蟒蛇菜谱]Python日志记录最佳实践
  4. CMD执行BCP命令
  5. Invalid Image Path - No image found at the path referenced under key "CFBundleIconFile": Icon.png
  6. mybatis3批量更新 批量插入
  7. Java 反射的基本应用
  8. 《30天自制操作系统》06_day_学习笔记
  9. .NET单元测试
  10. 前台页面验证中需要注意的一个与VARCHAR2(N BYTE)和VARCHAR2(N CHAR)的小细节
  11. Sublime Text3中文乱码及tabs中文方块的解决方案
  12. 精妙SQL语句介绍
  13. MyEclipse8.6安装svn(非link方式)
  14. EventBus通信小能手
  15. [SimplePlayer] 6. 音频同步
  16. IIS部署发布flask网站
  17. C++常见函数使用
  18. Linux 硬件RAID详解系统功能图
  19. openStack nova nova valid hosts 优化
  20. mysql元数据查询

热门文章

  1. 网页制作,网站制作中put和get的区别
  2. vue - .postcssrc.js
  3. jQuery实现滚动栏一直处于最底部
  4. 将object格式转为json格式
  5. mongodb - 查看数据库状态
  6. 详解Struts1中的struts-config.xml配置文件【一】
  7. C#通过WIN32 API实现嵌入程序窗体
  8. js setInterval()函数 [倒计时用]
  9. Resources.FindObjectsOfTypeAll<T>()的坑(Ghost prefab)
  10. scut客户端心跳超时和客户端断开测试