C#框架阅读笔记--引用参数ref和out区别
来源:互联网 发布:淘宝五金冠店铺 编辑:程序博客网 时间:2024/06/02 15:32
引用参数ref和out区别
这两个关键字的区别在于那个方法负责初始化引用对象,如果方法的参数标记为out,
那么调用者不希望在调用方法之前初始化对象,被调用的方法不能读取对象的值,而且被
调用的方法必须在返回之前为对象赋值。如果方法的参数标记为ref,那么调用者必须在
调用方法之前首先初始化参数的值,被调用的方法可以读取参数或者为参数赋值。
例2:
using System;
using System.IO;
public sealed class Program
{
public static void Main()
{
FileStream fs = null; //初始化为null (必要的操作)
//打开第一个待处理的文件
ProcessFiles(ref fs);
//如果有更多的需要处理的文件,则继续
for(; fs != null; ProcessFiles(ref fs))
{
//处理文件
fs.read();
}
}
private static void ProcessFiles(ref fs)
{
//如果先前的文件时打开的,则将其关闭
if(fs != null)
{
fs.close(); //关闭最后一个操作的文件
}
//打开下一个文件:如果没有文件,则返回null
if(noMoreFilesToProcess)
{
fs = null;
}
else
{
fs = new FileStream(...);
}
}
}
例3:如何利用ref关键字实现一个用于交换两个引用类型的方法:
public static void Swap(ref Object a, ref Object b)
{
Object t = b;
b = a;
a = t;
}
为了交换两个String对象的引用,看一下错误的代码:
public static void SomeMethod()
{
String s1 = "Jeffrey";
String s2 = "Kichter";
Swap(ref s1, ref s2);
Console.WriteLine(s1); //期望显示“Kichter”
Console.WriteLine(s2); //期望显示“Jeffrey”
}
但是,上述代码无法通过编译。问题在于按引用传递给方法的变量的类型必须与方法签名中
声明类型相同,换句话说,Swep希望有两个Object引用,而不是两个String应用。为了交换String
引用,需要向下面这样的代码:
public static void SomeMethod()
{
String s1 = "Jeffrey";
String s2 = "Richter";
//以引用方式传递的变量必须和方法期望的参数类型匹配
//将对象强制转换回字符串
Object o1 = s1, o2 = s2;
Swap(ref o1, ref o2);
// Now cast the objects back to strings.
s1 = (String)o1;
s2 = (String)o2;
Console.WriteLine(s1); //显示“Richter”
Console.WriteLine(s2); //显示“Jeffrey”
}
这个版本的SomeMethod可以通过编译, 并且如预期的一样执行。传递的参数必须与方法期望的参数相匹配,旨在确保类型安全
下面的代码(信号不会进行编译),显示了类型安全吃如何进行折中的:
internal sealed class SomeType
{
public Int32 m_val;
}
public sealed class Program
{
public static void Main()
{
SomeType st;
//下以行代码将产生错信息:error CS1503:参数‘1’:不能从‘ref SomeType’ 转换成‘ref objiect’
GetAnObject(out st);
Console.WriteLine(st.Mval);
}
private static void GetAnObject(out Object o)
{
o = new String('x',100);
}
}
前面代码中,Main显然希望GetAnObject方法返回一个SomeType对象。但是,因为GetAnObject的简明表示的是一个Object引用,
所以GetAnObject可以将o初始化某个类型的对象。在这个范例中,当GetAnObject返回Main时,st将引用String对象,这明显不是SomeType对象,
因此对Console.WriteLine的调用肯定会失败。幸亏c#编译器无法编译前面的代码,因为st是对SomeTypd
对象的引用,而GetAnObject要求的是Object对象引用。
可以用泛型(getneric)来修正这些方法,以便他们按照期望的方式运行,下面是前面示范的Swap方法的修正:
public static void Swap<T>(ref T a, ref T b)
{
T t = b;
b = a;
a = t;
}
这两个关键字的区别在于那个方法负责初始化引用对象,如果方法的参数标记为out,
那么调用者不希望在调用方法之前初始化对象,被调用的方法不能读取对象的值,而且被
调用的方法必须在返回之前为对象赋值。如果方法的参数标记为ref,那么调用者必须在
调用方法之前首先初始化参数的值,被调用的方法可以读取参数或者为参数赋值。
例2:
using System;
using System.IO;
public sealed class Program
{
public static void Main()
{
FileStream fs = null; //初始化为null (必要的操作)
//打开第一个待处理的文件
ProcessFiles(ref fs);
//如果有更多的需要处理的文件,则继续
for(; fs != null; ProcessFiles(ref fs))
{
//处理文件
fs.read();
}
}
private static void ProcessFiles(ref fs)
{
//如果先前的文件时打开的,则将其关闭
if(fs != null)
{
fs.close(); //关闭最后一个操作的文件
}
//打开下一个文件:如果没有文件,则返回null
if(noMoreFilesToProcess)
{
fs = null;
}
else
{
fs = new FileStream(...);
}
}
}
例3:如何利用ref关键字实现一个用于交换两个引用类型的方法:
public static void Swap(ref Object a, ref Object b)
{
Object t = b;
b = a;
a = t;
}
为了交换两个String对象的引用,看一下错误的代码:
public static void SomeMethod()
{
String s1 = "Jeffrey";
String s2 = "Kichter";
Swap(ref s1, ref s2);
Console.WriteLine(s1); //期望显示“Kichter”
Console.WriteLine(s2); //期望显示“Jeffrey”
}
但是,上述代码无法通过编译。问题在于按引用传递给方法的变量的类型必须与方法签名中
声明类型相同,换句话说,Swep希望有两个Object引用,而不是两个String应用。为了交换String
引用,需要向下面这样的代码:
public static void SomeMethod()
{
String s1 = "Jeffrey";
String s2 = "Richter";
//以引用方式传递的变量必须和方法期望的参数类型匹配
//将对象强制转换回字符串
Object o1 = s1, o2 = s2;
Swap(ref o1, ref o2);
// Now cast the objects back to strings.
s1 = (String)o1;
s2 = (String)o2;
Console.WriteLine(s1); //显示“Richter”
Console.WriteLine(s2); //显示“Jeffrey”
}
这个版本的SomeMethod可以通过编译, 并且如预期的一样执行。传递的参数必须与方法期望的参数相匹配,旨在确保类型安全
下面的代码(信号不会进行编译),显示了类型安全吃如何进行折中的:
internal sealed class SomeType
{
public Int32 m_val;
}
public sealed class Program
{
public static void Main()
{
SomeType st;
//下以行代码将产生错信息:error CS1503:参数‘1’:不能从‘ref SomeType’ 转换成‘ref objiect’
GetAnObject(out st);
Console.WriteLine(st.Mval);
}
private static void GetAnObject(out Object o)
{
o = new String('x',100);
}
}
前面代码中,Main显然希望GetAnObject方法返回一个SomeType对象。但是,因为GetAnObject的简明表示的是一个Object引用,
所以GetAnObject可以将o初始化某个类型的对象。在这个范例中,当GetAnObject返回Main时,st将引用String对象,这明显不是SomeType对象,
因此对Console.WriteLine的调用肯定会失败。幸亏c#编译器无法编译前面的代码,因为st是对SomeTypd
对象的引用,而GetAnObject要求的是Object对象引用。
可以用泛型(getneric)来修正这些方法,以便他们按照期望的方式运行,下面是前面示范的Swap方法的修正:
public static void Swap<T>(ref T a, ref T b)
{
T t = b;
b = a;
a = t;
}
- C#框架阅读笔记--引用参数ref和out区别
- c#方法参数ref和out区别
- C#引用类型参数加ref或out与不加ref或out的区别
- C# ref与out 引用和传值的区别
- C# out和ref区别
- C# 中ref 和out 参数的区别
- C#中 ref 和 out 参数的区别
- C#回顾学习笔记十六:out、ref和params参数
- c#方法中调用参数的值传递方式和引用传递方式,以及ref与out的区别
- c#方法中调用参数的值传递方式和引用传递方式,以及ref与out的区别
- C#的out参数和ref参数
- C#中的Ref参数和Out参数
- 【学习笔记】C#中Ref和Out关键字的区别:
- C#笔记之ref和out的区别
- 【黑马程序员】C#笔记之ref和out的区别
- C# 引用ref/out
- out参数和ref参数的区别
- out参数和ref参数区别
- cscope 用cs f操作时报告no cscope connections
- php 插入mysql汉字乱码
- C#框架阅读笔记--equals方法
- ubuntu 编译 Android 出现的若干错误及解决方法
- 一道特殊要求的字符串比较笔试题
- C#框架阅读笔记--引用参数ref和out区别
- php 获取参数 和 参数个数
- logical standby database can not create database link
- 云计算:知识社会的动力之源
- 確認Thread.Sleep(500)的對多線程的影響范圍
- C#框架阅读笔记--类和接口的继承
- Flex自定义虚线
- 用faad解码AAC(ADTS封装)
- java6内置JS引擎初接触