ref和out的用法 我刚学c#学到这里我很迷惑 不知道为什么要用 好处在哪里 请哪位高手跟我举个很简单的例子说说 谢谢
参数修饰符ref,out ,params的区别:
params 关键字可以指定在参数数目可变处采用参数的方法参数。
在方法声明中的 params 关键字之后不允许任何其他参数,并且在方法声明中只允许一个 params 关键字。
示例
// cs_params.cs
using System;
public class MyClass
{
public static void UseParams(params int[] list)
{
for ( int i = 0 ; i < list.Length ; i++ )
Console.WriteLine(list[i]);
Console.WriteLine();
}
public static void UseParams2(params object[] list)
{
for ( int i = 0 ; i < list.Length ; i++ )
Console.WriteLine(list[i]);
Console.WriteLine();
}
public static void Main()
{
UseParams(1, 2, 3);
UseParams2(1, 'a', "test");
int[] myarray = new int[3] {10,11,12};
UseParams(myarray);
}
}
输出
1
2
3
1
a
test
10
11
12
===============================================
方法参数上的 out 方法参数关键字使方法引用传递到方法的同一个变量。当控制传递回调用方法时,在方法中对参数所做的任何更改都将反映在该变量中。
当希望方法返回多个值时,声明 out 方法非常有用。使用 out 参数的方法仍然可以返回一个值。一个方法可以有一个以上的 out 参数。
若要使用 out 参数,必须将参数作为 out 参数显式传递到方法。out 参数的值不会传递到 out 参数。
不必初始化作为 out 参数传递的变量。然而,必须在方法返回之前为 out 参数赋值。
属性不是变量,不能作为 out 参数传递。
如果两个方法的声明仅在 out 的使用方面不同,则会发生重载。不过,无法定义仅在 ref 和 out 方面不同的重载。例如,以下重载声明是有效的:
class MyClass
{
public void MyMethod(int i) {i = 10;}
public void MyMethod(out int i) {i = 10;}
}
而以下重载声明是无效的:
class MyClass
{
public void MyMethod(out int i) {i = 10;}
public void MyMethod(ref int i) {i = 10;}
}
有关传递数组的信息,请参见使用 ref 和 out 传递数组。
示例
// cs_out.cs
using System;
public class MyClass
{
public static int TestOut(out char i)
{
i = 'b';
return -1;
}
public static void Main()
{
char i; // variable need not be initialized
Console.WriteLine(TestOut(out i));
Console.WriteLine(i);
}
}
输出
-1
b
========================================
方法参数上的 ref 方法参数关键字使方法引用传递到方法的同一个变量。当控制传递回调用方法时,在方法中对参数所做的任何更改都将反映在该变量中。
若要使用 ref 参数,必须将参数作为 ref 参数显式传递到方法。ref 参数的值被传递到 ref 参数。
传递到 ref 参数的参数必须最先初始化。将此方法与 out 参数相比,后者的参数在传递到 out 参数之前不必显式初始化。
属性不是变量,不能作为 ref 参数传递。
如果两种方法的声明仅在它们对 ref 的使用方面不同,则将出现重载。但是,无法定义仅在 ref 和 out 方面不同的重载。例如,以下重载声明是有效的:
class MyClass
{
public void MyMethod(int i) {i = 10;}
public void MyMethod(ref int i) {i = 10;}
}
但以下重载声明是无效的:
class MyClass
{
public void MyMethod(out int i) {i = 10;}
public void MyMethod(ref int i) {i = 10;}
}
有关传递数组的信息,请参见使用 ref 和 out 传递数组。
示例
// cs_ref.cs
using System;
public class MyClass
{
public static void TestRef(ref char i)
{
// The value of i will be changed in the calling method
i = 'b';
}
public static void TestNoRef(char i)
{
// The value of i will be unchanged in the calling method
i = 'c';
}
// This method passes a variable as a ref parameter; the value of the
// variable is changed after control passes back to this method.
// The same variable is passed as a value parameter; the value of the
// variable is unchanged after control is passed back to this method.
public static void Main()
{
char i = 'a'; // variable must be initialized
TestRef(ref i); // the arg must be passed as ref
Console.WriteLine(i);
TestNoRef(i);
Console.WriteLine(i);
}
}
输出
b
b
参考资料:MSDN
params 关键字可以指定在参数数目可变处采用参数的方法参数。
在方法声明中的 params 关键字之后不允许任何其他参数,并且在方法声明中只允许一个 params 关键字。
示例
// cs_params.cs
using System;
public class MyClass
{
public static void UseParams(params int[] list)
{
for ( int i = 0 ; i < list.Length ; i++ )
Console.WriteLine(list[i]);
Console.WriteLine();
}
public static void UseParams2(params object[] list)
{
for ( int i = 0 ; i < list.Length ; i++ )
Console.WriteLine(list[i]);
Console.WriteLine();
}
public static void Main()
{
UseParams(1, 2, 3);
UseParams2(1, 'a', "test");
int[] myarray = new int[3] {10,11,12};
UseParams(myarray);
}
}
输出
1
2
3
1
a
test
10
11
12
===============================================
方法参数上的 out 方法参数关键字使方法引用传递到方法的同一个变量。当控制传递回调用方法时,在方法中对参数所做的任何更改都将反映在该变量中。
当希望方法返回多个值时,声明 out 方法非常有用。使用 out 参数的方法仍然可以返回一个值。一个方法可以有一个以上的 out 参数。
若要使用 out 参数,必须将参数作为 out 参数显式传递到方法。out 参数的值不会传递到 out 参数。
不必初始化作为 out 参数传递的变量。然而,必须在方法返回之前为 out 参数赋值。
属性不是变量,不能作为 out 参数传递。
如果两个方法的声明仅在 out 的使用方面不同,则会发生重载。不过,无法定义仅在 ref 和 out 方面不同的重载。例如,以下重载声明是有效的:
class MyClass
{
public void MyMethod(int i) {i = 10;}
public void MyMethod(out int i) {i = 10;}
}
而以下重载声明是无效的:
class MyClass
{
public void MyMethod(out int i) {i = 10;}
public void MyMethod(ref int i) {i = 10;}
}
有关传递数组的信息,请参见使用 ref 和 out 传递数组。
示例
// cs_out.cs
using System;
public class MyClass
{
public static int TestOut(out char i)
{
i = 'b';
return -1;
}
public static void Main()
{
char i; // variable need not be initialized
Console.WriteLine(TestOut(out i));
Console.WriteLine(i);
}
}
输出
-1
b
========================================
方法参数上的 ref 方法参数关键字使方法引用传递到方法的同一个变量。当控制传递回调用方法时,在方法中对参数所做的任何更改都将反映在该变量中。
若要使用 ref 参数,必须将参数作为 ref 参数显式传递到方法。ref 参数的值被传递到 ref 参数。
传递到 ref 参数的参数必须最先初始化。将此方法与 out 参数相比,后者的参数在传递到 out 参数之前不必显式初始化。
属性不是变量,不能作为 ref 参数传递。
如果两种方法的声明仅在它们对 ref 的使用方面不同,则将出现重载。但是,无法定义仅在 ref 和 out 方面不同的重载。例如,以下重载声明是有效的:
class MyClass
{
public void MyMethod(int i) {i = 10;}
public void MyMethod(ref int i) {i = 10;}
}
但以下重载声明是无效的:
class MyClass
{
public void MyMethod(out int i) {i = 10;}
public void MyMethod(ref int i) {i = 10;}
}
有关传递数组的信息,请参见使用 ref 和 out 传递数组。
示例
// cs_ref.cs
using System;
public class MyClass
{
public static void TestRef(ref char i)
{
// The value of i will be changed in the calling method
i = 'b';
}
public static void TestNoRef(char i)
{
// The value of i will be unchanged in the calling method
i = 'c';
}
// This method passes a variable as a ref parameter; the value of the
// variable is changed after control passes back to this method.
// The same variable is passed as a value parameter; the value of the
// variable is unchanged after control is passed back to this method.
public static void Main()
{
char i = 'a'; // variable must be initialized
TestRef(ref i); // the arg must be passed as ref
Console.WriteLine(i);
TestNoRef(i);
Console.WriteLine(i);
}
}
输出
b
b
参考资料:MSDN
参考资料:MSDN
温馨提示:答案为网友推荐,仅供参考
第1个回答 2007-07-13
这是我以前做的部分学习笔记,貌似正好可以解决你的问题,我另加了一点自己对书的翻译补充,你可以参考下。
首先要了解值类型(value type)和引用类型(refrence type)的区别。
引用类型指的是类(class),接口(interface),数组(array),或委托(delegate)类型。
值类型指的是结构(struct)或枚举(enum)类型,C#提供了一系列预定义的结构类型,称做简单类型。
简单类型就是C#中由保留字标识的类型,这些类型其实只是System名称空间中类型的别名而已。
以下是C#中简单类型的保留字和其对应实际类型。
sbyte
System.SByte
byte
System.Byte
short
System.Int16
ushort
System.UInt16
int
System.Int32
uint
System.UInt32
long
System.Int64
ulong
System.UInt64
char
System.Char
float
System.Single
double
System.Double
bool
System.Boolean
decimal
System.Decimal
1、关键字ref
在C#中,值类型的函数传值默认使用的是按值传递,这就意味着当一个值类型的对象传入函数时,该函数为这个参数创建了一份属于自己的拷贝,当函数结束时,这份拷贝会被自动销毁。有时候我们需要在函数中对传入参数的本体进行修改,而不是这个参数的拷贝,这时我们就需要使用C#提供的ref关键字来实现值类型的按引用传递。以下是交换2个变量的值的例子:
class PassByRefDemon
{
static void Main()
{
int a = 1, b = 2;
// not what you want
SwapByVal(a, b);
System.Console.WriteLine(a + " " + b);
// now it works!
SwapByRef(ref a, ref b);
System.Console.WriteLine(a + " " + b);
}
static void SwapByVal(int lhs, int rhs)
{
int tmp = lhs;
lhs = rhs;
rhs = tmp;
}
static void SwapByRef(ref int lhs, ref int rhs)
{
int tmp = lhs;
lhs = rhs;
rhs = tmp;
}
}
可以看出只有使用了按引用传参的函数SwapByRef,Main函数中a和b的值才会被交换,否则交换的只是Swap函数中对传入参数a、b的拷贝的值而已。
2、关键字out
C#是一个强赋值检查(definite assignment)(不知道翻译地对不对),的语言,这意味着任何变量在他们被使用之前都应该被明确地初始化或赋值,以下是试图使用未初始化的变量引起的编译错误:
class UseUninitializedVariable
{
static void Main()
{
int a;
System.Console.WriteLine(a); // compile error
}
}
而有的时候你在创建一个变量之后,你并不需要使用它的初始值,例如你需要获得系统的当前时间:
class GetSysTime1
{
static void Main()
{
int theHour = 0; // seems silly
int theMinute = 0;
int theSecond = 0;
GetTime(ref theHour, ref theMinute, ref theSecond);
System.Console.WriteLine("Now is: " + theHour + ':' + theMinute + ':' + theSecond);
}
static void GetTime(ref int theHour, ref int theMinute, ref int theSecond)
{
theHour = System.DateTime.Now.Hour;
theMinute = System.DateTime.Now.Minute;
theSecond = System.DateTime.Now.Second;
}
}
如果为其提供一个初值0仅仅是为了压制编译器的"Use of unassigned local variable xxx"错误,那么这种赋值多少有些无聊和愚蠢,因为你在他们被赋值之后将马上把他们按引用传递给函数GetTime以获得时间,所以这时候我们就需要C#提供的另外一个关键字来改变这种情形,使用out来克制C#的definite assignment。
class GetSysTime2
{
static void Main()
{
int theHour;
int theMinute;
int theSecond;
// now it's OK
GetTime(out theHour, out theMinute, out theSecond);
System.Console.WriteLine("Now is: " + theHour + ':' + theMinute + ':' + theSecond);
}
static void GetTime(out int theHour, out int theMinute, out int theSecond)
{
theHour = System.DateTime.Now.Hour;
theMinute = System.DateTime.Now.Minute;
theSecond = System.DateTime.Now.Second;
}
}
首先要了解值类型(value type)和引用类型(refrence type)的区别。
引用类型指的是类(class),接口(interface),数组(array),或委托(delegate)类型。
值类型指的是结构(struct)或枚举(enum)类型,C#提供了一系列预定义的结构类型,称做简单类型。
简单类型就是C#中由保留字标识的类型,这些类型其实只是System名称空间中类型的别名而已。
以下是C#中简单类型的保留字和其对应实际类型。
sbyte
System.SByte
byte
System.Byte
short
System.Int16
ushort
System.UInt16
int
System.Int32
uint
System.UInt32
long
System.Int64
ulong
System.UInt64
char
System.Char
float
System.Single
double
System.Double
bool
System.Boolean
decimal
System.Decimal
1、关键字ref
在C#中,值类型的函数传值默认使用的是按值传递,这就意味着当一个值类型的对象传入函数时,该函数为这个参数创建了一份属于自己的拷贝,当函数结束时,这份拷贝会被自动销毁。有时候我们需要在函数中对传入参数的本体进行修改,而不是这个参数的拷贝,这时我们就需要使用C#提供的ref关键字来实现值类型的按引用传递。以下是交换2个变量的值的例子:
class PassByRefDemon
{
static void Main()
{
int a = 1, b = 2;
// not what you want
SwapByVal(a, b);
System.Console.WriteLine(a + " " + b);
// now it works!
SwapByRef(ref a, ref b);
System.Console.WriteLine(a + " " + b);
}
static void SwapByVal(int lhs, int rhs)
{
int tmp = lhs;
lhs = rhs;
rhs = tmp;
}
static void SwapByRef(ref int lhs, ref int rhs)
{
int tmp = lhs;
lhs = rhs;
rhs = tmp;
}
}
可以看出只有使用了按引用传参的函数SwapByRef,Main函数中a和b的值才会被交换,否则交换的只是Swap函数中对传入参数a、b的拷贝的值而已。
2、关键字out
C#是一个强赋值检查(definite assignment)(不知道翻译地对不对),的语言,这意味着任何变量在他们被使用之前都应该被明确地初始化或赋值,以下是试图使用未初始化的变量引起的编译错误:
class UseUninitializedVariable
{
static void Main()
{
int a;
System.Console.WriteLine(a); // compile error
}
}
而有的时候你在创建一个变量之后,你并不需要使用它的初始值,例如你需要获得系统的当前时间:
class GetSysTime1
{
static void Main()
{
int theHour = 0; // seems silly
int theMinute = 0;
int theSecond = 0;
GetTime(ref theHour, ref theMinute, ref theSecond);
System.Console.WriteLine("Now is: " + theHour + ':' + theMinute + ':' + theSecond);
}
static void GetTime(ref int theHour, ref int theMinute, ref int theSecond)
{
theHour = System.DateTime.Now.Hour;
theMinute = System.DateTime.Now.Minute;
theSecond = System.DateTime.Now.Second;
}
}
如果为其提供一个初值0仅仅是为了压制编译器的"Use of unassigned local variable xxx"错误,那么这种赋值多少有些无聊和愚蠢,因为你在他们被赋值之后将马上把他们按引用传递给函数GetTime以获得时间,所以这时候我们就需要C#提供的另外一个关键字来改变这种情形,使用out来克制C#的definite assignment。
class GetSysTime2
{
static void Main()
{
int theHour;
int theMinute;
int theSecond;
// now it's OK
GetTime(out theHour, out theMinute, out theSecond);
System.Console.WriteLine("Now is: " + theHour + ':' + theMinute + ':' + theSecond);
}
static void GetTime(out int theHour, out int theMinute, out int theSecond)
{
theHour = System.DateTime.Now.Hour;
theMinute = System.DateTime.Now.Minute;
theSecond = System.DateTime.Now.Second;
}
}
第2个回答 2007-07-15
哎,被自己的钻研精神折服了,才发现没必要研究他们传递方式是怎样的,只需要注意.
out 参数在使用前不必初始化,使用时必须赋值初始化.其余一样的.
ref 参数在使用前必须初始化,使用时不必赋值初始化.其余一样的.
out 参数在使用前不必初始化,使用时必须赋值初始化.其余一样的.
ref 参数在使用前必须初始化,使用时不必赋值初始化.其余一样的.