类类型作为方法的参数时,使用 ref 和不使用ref的区别?..请高手解答,顶都有分

yeerh 2006-09-06 11:52:13
请先看程序:
using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Data.SqlClient;

namespace Refesh
{
class Program
{
static void Main(string[] args)
{
SqlConnection conn = new SqlConnection("server=localhost;DataBase=ABC;uid=sa;pwd=password;");
DataTable dt = new DataTable("ABC");
setConn(conn);
Console.WriteLine(conn.ConnectionString);
setConn(ref conn);
Console.WriteLine(conn.ConnectionString);
setDataTable(dt);
Console.WriteLine(dt.TableName);
setDataTable(ref dt);
Console.WriteLine(dt.TableName);
Console.ReadLine();
}

static void setDataTable(DataTable dt)
{
dt = null;
dt = new DataTable("XYZ");
}
static void setDataTable(ref DataTable dt)
{
dt = null;
dt = new DataTable("XYZ");
}
static void setConn (SqlConnection conn)
{
conn = null;
conn = new SqlConnection("server=localhostSSS;DataBase=XYZ;uid=saS;pwd=XXX;");
}
static void setConn(ref SqlConnection conn)
{
conn = null;
conn = new SqlConnection("server=localhostSSS;DataBase=XYZ;uid=saS;pwd=XXX;");
}
}
}
想一下会输出什么结果....
...全文
471 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
yeerh 2006-09-06
  • 打赏
  • 举报
回复
肯定是有区别的.
把上面的代码精减了...
请先测试...再说原因
using System;
using System.Collections.Generic;
using System.Text;
using System.Data;

namespace Refesh
{
class Program
{
static void Main(string[] args)
{
DataTable dt1 = new DataTable("初始表名");
DataTable dt2 = new DataTable("初始表名");
Console.WriteLine("初始表名相同");

setDataTable(dt1);
Console.WriteLine("执行不带ref的方法,结果为: " + dt1.TableName);
setDataTable(ref dt2);
Console.WriteLine("执行带ref的方法,结果为: " + dt2.TableName);
Console.ReadLine();
}

static void setDataTable(DataTable dt)
{
dt = new DataTable("新表名");
}
static void setDataTable(ref DataTable dt)
{
dt = new DataTable("新表名");
}
}
}
www_123du_com 2006-09-06
  • 打赏
  • 举报
回复
说到参数传递,必须得弄清值类型和引用类型:
(为了容易表达,我暂且命名存放在堆中的内容为堆中对象,存放在栈上的内容为栈中对象。)
值类型存放在栈中,直接访问。如果有:int a=0;int b=a;就产生了两个栈中对象。
引用类型需要在堆中显式分配,且不能直接访问,需要在栈中分配一个栈中对象(C++叫指针,C#叫引用)指向其堆中对象。
如果:
StringBuilder strb = new StringBuilder();
StringBuilder strb2 = strb;
则在堆中只有一个堆中对象,只是栈中有两个栈中对象指向堆中对象。
可以看出:每个变量都是一个栈中对象。不管是值类型还是引用类型,只是值类型的栈中对象就是其内容,而引用类型的栈中对象只是一个指向堆中对象的地址。

参数传递分值传递和引用传递两种。
通常,在没有显式指出ref和out时都是值传递。

值传递:传的是对象的值拷贝。(即函数内参数对象是调用时传递的对象的栈中对象的拷贝。)
引用传递:传的是栈中对象的地址。(即函数内参数对象与调用时传递的对象完全是同一栈中对象。)
现在用例子来说明传值跟传地址的不同:


private void button2_Click(object sender, System.EventArgs e)
{
StringBuilder strb1 = new StringBuilder();
StringBuilder strb2 = new StringBuilder();
Test1(strb1);
Test2(ref strb2);
string str1 = strb1.ToString(); //str1值:"A"
string str2 = strb2.ToString(); //str2值:"BC"
}

void Test1(StringBuilder strb)
{
//strb和strb1是两个栈中对象,但指向相同的地址,这个操作是改变堆中对象
strb.Append("A");

//这里将strb指向一个新的堆中对象,所以后面的操作与strb1指向的栈中对象无关
strb = new StringBuilder("B");
strb.Append("C");
}

void Test2(ref StringBuilder strb)
{
//这里的strb和strb2是同一个栈中对象,所以改变strb的值使其指向另一个对象也等于改变strb2
strb = new StringBuilder("B");
strb.Append("C");
}
www_123du_com 2006-09-06
  • 打赏
  • 举报
回复
我自己的见解:

http://blog.csdn.net/www_123du_com/archive/2006/08/26/1123676.aspx
yeerh 2006-09-06
  • 打赏
  • 举报
回复
把 dt = null 和 conn = null;
去掉....同样不影响执行结果..
lovefootball 2006-09-06
  • 打赏
  • 举报
回复
static void setDataTable(DataTable dt)
在这个里面new了
deadshot123 2006-09-06
  • 打赏
  • 举报
回复
没有ref可以更改引用所指对象的内容,但是不能改变引用本身

有ref可以改变引用本身

如果你把
static void setDataTable(DataTable dt)
{
dt = null;
dt = new DataTable("XYZ");
}

Change to
static void setDataTable(DataTable dt)
{
dt.TableName="XYZ";
}
deadshot123 2006-09-06
  • 打赏
  • 举报
回复
测试一下 不一样......
xlshen_lxz 2006-09-06
  • 打赏
  • 举报
回复
当传递对象时,没有什么区别。

加了ref就是引用传递,否则就是值传递。但对于对象来说,没什么区别
TryToday 2006-09-06
  • 打赏
  • 举报
回复
应该没有区别,都会修改参数的值。
deadshot123 2006-09-06
  • 打赏
  • 举报
回复
没有区别 因为DataTable和SqlConnection这两个都是传引用

比如
public void Change(int input)和public void Change(ref int input)这样就有区别

第一个传值,在方法体内改变不了input的值,而后者传引用,可以在方法体内更改input的值
ClementDik 2006-09-06
  • 打赏
  • 举报
回复
简单来说:不用ref的话,只能改变当前实例的内容,而不能创建新实例。
比如:
void func1()
{
Class1 a = new Class1();
a.Property1 = 0;
this.func2(a);
Console.WriteLine(a.Property1);
}
void func2(Class1 a)
{
a = new Class1();
a.Property1 = 10;
}

输出仍然为0。如果func2使用了ref那么输出就为10。
jijl2001 2006-09-06
  • 打赏
  • 举报
回复
区别在于ref能够修改对象地址,没有ref只能修改对象本身
tesling 2006-09-06
  • 打赏
  • 举报
回复
mark
yeerh 2006-09-06
  • 打赏
  • 举报
回复
楼上正解.........
rosanshao 2006-09-06
  • 打赏
  • 举报
回复
引用类型的变量不直接包含其数据;它包含的是对其数据的引用。当通过值传递引用类型的参数时,有可能更改引用所指向的数据,如某类成员的值。但是无法更改引用本身的值;也就是说,不能使用相同的引用为新类分配内存并使之在块外保持。若要这样做,应使用 ref 或 out 关键字传递参数。为了简单起见,下面的示例使用 ref。

示例:通过值传递引用类型
下面的示例演示通过值向 Change 方法传递引用类型的参数 arr。由于该参数是对 arr 的引用,所以有可能更改数组元素的值。但是,试图将参数重新分配到不同的内存位置时,该操作仅在方法内有效,并不影响原始变量 arr。

C# 复制代码
class PassingRefByVal
{
static void Change(int[] pArray)
{
pArray[0] = 888; // This change affects the original element.
pArray = new int[5] {-3, -1, -2, -3, -4}; // This change is local.
System.Console.WriteLine("Inside the method, the first element is: {0}", pArray[0]);
}

static void Main()
{
int[] arr = {1, 4, 5};
System.Console.WriteLine("Inside Main, before calling the method, the first element is: {0}", arr [0]);

Change(arr);
System.Console.WriteLine("Inside Main, after calling the method, the first element is: {0}", arr [0]);
}
}



输出
Inside Main, before calling the method, the first element is: 1

Inside the method, the first element is: -3

Inside Main, after calling the method, the first element is: 888

代码讨论
在上个示例中,数组 arr 为引用类型,在未使用 ref 参数的情况下传递给方法。在此情况下,将向方法传递指向 arr 的引用的一个副本。输出显示方法有可能更改数组元素的内容,在这种情况下,从 1 改为 888。但是,在 Change 方法内使用 new 运算符来分配新的内存部分,将使变量 pArray 引用新的数组。因此,这之后的任何更改都不会影响原始数组 arr(它是在 Main 内创建的)。实际上,本示例中创建了两个数组,一个在 Main 内,一个在 Change 方法内。

示例:通过引用传递引用类型
本示例除在方法头和调用中使用 ref 关键字以外,其余与上个示例相同。方法内发生的任何更改都会影响调用程序中的原始变量。

C# 复制代码
class PassingRefByRef
{
static void Change(ref int[] pArray)
{
// Both of the following changes will affect the original variables:
pArray[0] = 888;
pArray = new int[5] {-3, -1, -2, -3, -4};
System.Console.WriteLine("Inside the method, the first element is: {0}", pArray[0]);
}

static void Main()
{
int[] arr = {1, 4, 5};
System.Console.WriteLine("Inside Main, before calling the method, the first element is: {0}", arr[0]);

Change(ref arr);
System.Console.WriteLine("Inside Main, after calling the method, the first element is: {0}", arr[0]);
}
}


真相重于对错 2006-09-06
  • 打赏
  • 举报
回复
区别很大
ref object 相当于指向指针的指针,就是说你可以修改object的地址
object 指针,你只能修改object的值,却不能修改它的指向

110,533

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

试试用AI创作助手写篇文章吧