用户名: 密码: 免费注册 忘记密码? 加入收藏 | 设为首页
对于关键字Ref和Out的理解
学院首页 | 资讯中心 | 服务器软件 | 系统工具 | 系统软件 | 办公软件 | 聊天软件 | 多 媒 体 | 网页制作 | 网站运营 | 平面设计
艺术欣赏 | 数据库软件 | 程序开发 | 网络组建 | 源码下载 | 驱动下载 | 软件下载 | 电脑安全 | IT创业 | IT博客 | IT社区
硬件数码导航 | 硬件频道 | 本本频道 | MP3频道 | 相机频道 | 手机频道 | 显卡频道 | LCD 频道 | 音箱音频 | 行情 | 评测 | 导购
学院专题 软件 - 系统 - 办公 - 聊天 - 多媒体 - 网页制作 - IT创业 - 运营 - 平面 - 设计欣赏 - 数据库 - 程序 - 服务器 - 组网

 当前位置: 首页>>技术频道>>程序>>c#教程>>正文

对于关键字Ref和Out的理解

日期:2006-9-15 4:21:03     来源:csdn   编辑:   

类型介绍

在几乎所有的OOP语言中,都存在2种类型的值 。

  1. 值类型
  2. 引用类型

以C#为例:其值类型为sbyte,byte,char,short,ushort,int,uint,long和ulong,float和double,当然还有decimal和bool 。 而引用类型则是string和object 。

我想说的

我想说的就是——Ref和Out把我弄糊涂的原因是,当时没有认真的去分析它对不同类型所做出的不同的动作 。

对于值类型 。

使用了Ref和Out的效果就几乎和C中使用了指针变量一样 。 它能够让你直接对原数进行操作,而不是对那个原数的Copy进行操作 。 举个小例子:

using System;
namespace ConsoleApplication4
{
///
/// Class1 的摘要说明 。
///

class Class1
{
///
/// 应用程序的主入口点 。
///

[STAThread]
static void Main(string[] args)
{
int a = 5;
int b;
squareRef(ref a);
squareOut(out b);
Console.WriteLine("The a in the Main is: " + a);
Console.WriteLine("The b in the Main is: " + b);
}
static void squareRef(ref int x)
{
x = x * x;
Console.WriteLine("The x in the squareRef is: " + x);
}
static void squareOut(out int y)
{
y = 10;
y = y * y;
Console.WriteLine("The y in the squareOut is: " + y);
}
}
}

显示的结果就是——25 100 25 100 。

这样的话,就达到了和C中的指针变量一样的作用 。

对于引用类型 。

对于引用类型就比较难理解了 。

先要了解到这一层——就是当一个方法接收到一个引用类型的变量的时候,它将获得这个引用(Reference)的一个Copy 。 由于Ref关键字可以用来向方法传递引用 。 所以,如果这个功能被误用了——比如:当一个如数组类型的引用对象用关键字Ref传递的时候,被调用的方法实际上已经控制了传递过来的引用本身 。 这样将使得被调用方法能用不同的对象甚至NULL来代替调用者的原始引用!

如图 。 内存地址为2000的变量arrayA中其实存放着数组{1,2,3,4,……}的内存起始地址10000 。 如果一个方法fun()使用fun( arrayA[] )的话,它将顺利的获得数据10000,但这个10000将放在一个Copy中,不会放到内存的2000位置 。 而这个时候我们如果使用fun( ref arrayA[] )的话,我们得到的值就是2000啦(也就是说,被调用方法能够修改掉arrayA中的那个引用,使之不再指向10000,甚至可以用NULL来代替10000,这样的话,那个10000地址中的数据可能就要被垃圾回收机制清理了 。

有个例子:

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
namespace RefOut
{
///
/// Form1 的摘要说明 。
///

public class Form1 : System.Windows.Forms.Form
{
private System.Windows.Forms.Button button1;
private System.Windows.Forms.Label label1;
///
/// 必需的设计器变量 。
///

private System.ComponentModel.Container components = null;

public Form1()
{
//
// Windows 窗体设计器支持所必需的
//
InitializeComponent();
//
// TODO: 在 InitializeComponent 调用后添加任何构造函数代码
//
}
///
/// 清理所有正在使用的资源 。
///

protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
#region Windows 窗体设计器生成的代码
///
/// 设计器支持所需的方法 - 不要使用代码编辑器修改
/// 此方法的内容 。
///

private void InitializeComponent()
{
this.button1 = new System.Windows.Forms.Button();
this.label1 = new System.Windows.Forms.Label();
this.SuspendLayout();
//
// button1
//
this.button1.Dock = System.Windows.Forms.DockStyle.Top;
this.button1.Location = new System.Drawing.Point(0, 0);
this.button1.Name = "button1";
this.button1.Size = new System.Drawing.Size(480, 32);
this.button1.TabIndex = 0;
this.button1.Text = "显示输出";
this.button1.Click += new System.EventHandler(this.button1_Click);
//
// label1
//
this.label1.Location = new System.Drawing.Point(8, 48);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(456, 336);
this.label1.TabIndex = 1;
this.label1.Text = "label1";
//
// Form1
//
this.AutoScaleBaseSize = new System.Drawing.Size(6, 14);
this.ClientSize = new System.Drawing.Size(480, 405);
this.Controls.Add(this.label1);
this.Controls.Add(this.button1);
this.MaximizeBox = false;
this.MinimizeBox = false;
this.Name = "Form1";
this.Text = "Ref & Out";
this.ResumeLayout(false);
}
#endregion
///
/// 应用程序的主入口点 。
///

[STAThread]
static void Main()
{
Application.Run(new Form1());
}
private void button1_Click(object sender, System.EventArgs e)
{
int[] firstArray = {1, 2, 3};
int[] firstArrayCopy = firstArray;
this.label1.Text = "Test Passing firstArray reference by value";
this.label1.Text += "\n\nContents of firstArray before calling FirstDouble:\n\t";

for(int i = 0;i < firstArray.Length; i++)
{
this.label1.Text += firstArray[i] + " ";
}
FirstDouble(firstArray);
this.label1.Text += "\n\nContents of firstArray after calling FirstDouble.\n\t";
for(int i=0;i {
this.label1.Text += firstArray[i] + " ";
}
if(firstArray == firstArrayCopy)
this.label1.Text +="\n\nThe references refer to the same array.\n";
else
this.label1.Text +="\n\nThe reference refer to different arrays.\n";
int[] secondArray = {1, 2, 3};
int[] secondArrayCopy = secondArray;

this.label1.Text += "\nTest passing secondArray reference by reference.";
this.label1.Text += "\n\nContents of secondArray before calling SecondDouble:\n\t";
for(int i=0;i {
this.label1.Text += secondArray[i] + " ";
}
SecondDouble(ref secondArray);
this.label1.Text +="\n\nContents of secondArray after calling SecondDouble:\n\t";

for(int i=0; i {
this.label1.Text += secondArray[i] + " ";
}
if(secondArray== secondArrayCopy)
this.label1.Text += "\n\nThe reference refer to the same array.";
else
this.label1.Text += "\n\nThe reference refer to different arrays.";
this.label1.Text += "\n___________________heshi_________________\nsecondarray\n";
for(int i = 0;i {
this.label1.Text += secondArray[i] + " ";
}
this.label1.Text +="\nsecondarraycopy\n";
for(int i=0;i {
this.label1.Text += secondArrayCopy[i] + " ";
}

}
void FirstDouble(int[] array)
{
for(int i = 0;i array[i] *= 2;
array = new int[] {11, 12, 13};
}
void SecondDouble(ref int[] array)
{
for(int i=0;i {
array[i] *= 2;
}
array = new int[] {11, 12, 13};
}
}
}
运行后的结果是:运行后的结果

这个就说明了被调用的程序已经改变了原有的Reference 。

总结

总的说来,Ref和Out这两个关键字都能够提供相似的功效,其作用也很像C中的指针变量 。 稍有不同之处是:

  1. 使用Ref型参数时,传入的参数必须先被初始化 。 而Out则不需要,对Out而言,就必须在方法中对其完成初始化 。
  2. 使用Ref和Out时都必须注意,在方法的参数和执行方法时,都要加Ref或Out关键字 。 以满足匹配 。
  3. Out更适合用在需要Return多个返回值的地方,而Ref则用在需要被调用的方法修改调用者的引用的时候 。
gigi_miao
  ▼ 下一篇新闻 没有了
  ▲ 上一篇新闻 用C#创建PDA应用程序的柱形图控件        网友发表观点请进入=>



我要纠错】【进入论坛交流】【关闭此页

文章搜索
   
最新文章

 
·千名爱好者参与首届PHP调查
·腾讯称QQ通讯信息密钥加密 不会被
·雅虎反超Google排名搜索第二
·中搜等十余家IT企业因流氓软件被
·盛大前员工克隆网游装备获暴利被
·凤凰网将向迅雷提供娱乐及宽带内
·信产部出手规范 新浪式企业法律架
·雅虎中国称旗下软件早已没有流氓
·中搜停止划词搜索与流氓软件决裂

广告赞助
相关文章 相关教程下载
焦点信息
·腾讯称QQ通讯信息密钥加密 不会被监听
·信产部出手规范 新浪式企业法律架构不得不改
·盛大前员工克隆网游装备获暴利被追刑责
·凤凰网将向迅雷提供娱乐及宽带内容
·雅虎中国称旗下软件早已没有流氓问题
·雅虎反超Google排名搜索第二
网友评论:(评论内容只代表网友观点,与本站立场无关!)
发表评论     Hard168社区推荐帖子
姓 名: *
* 请网友遵纪守法并注意语言文明。
IT人物推荐

王江民
马云
柳传志



关于本站    联络方式    广告服务    意见信箱    加入收藏   设为首页    -
本站部分内容来自网上,如有侵权部分,敬请告知,我们会在24小时内给予处理
版权所有:Hard168.Com,如需转载文章请与我们取得联系
京ICP备05063857号 Designed by Hard168.Com
对于关键字Ref和Out的理解