ref和out的应用
要深刻理解ref和out的应用,
不仅从语法的角度,更要从面向对象【OO】的角度去理解和把握。
一、首先应该真正理解“方法”
方法:
1、语法的角度:略
2、OO的角度:方法是对现实行为或操作的一种模拟
比如:学生的上课,考试,面试等行为都可以用方法来模拟,
【方法包含普通方法,虚方法,抽象方法,……】
二、这里我们要重点讨论方法的返回值
1、有些方法不需要返回值,比如:
实例1:我今天心情好,下班后去逛超市,但是不买任何东西
实例1分析:
方法构成 |
|
不需要花钱 |
方法无参数 |
不买任何东西 |
方法无返回值 |
实例1可以用以下方法来模拟
void 逛超市()
{
//随意逛逛
}
2、有些方法需要返回值也需要参数,比如:
实例2:我今天下班后去超市买一箱牛奶
实例2分析:
方法构成 |
|
需要花*出*钱 |
方法有参数 |
买*回*一箱牛奶 |
方法有返回值 |
实例2可以用以下方法来模拟
int 逛超市(double 钱)
{
//花*出*钱
return 一箱牛奶;
}
三、ref ,out的用法
对于
实例2:我今天下班后去超市买一箱牛奶
实际我们有很多模拟的方式,如:方式1,方式2,方式3
方式1:用*有*参数*有*返回值的方法来模拟,如上
方法构成 |
|
需要花*出*钱 |
方法有参数,用一个参数{默认参数,传入值} |
买*回*一箱牛奶 |
方法有返回值{用return返回值,传出值} |
方式2:用*有*参数*没有*返回值的方法来模拟,让函数增加一个out参数,
让这个参数起到返回值的作用即传出值。
方法构成 |
|
需要花*出*钱 |
方法有参数, 一个为默认参数 {传入值} 另一个为out参数{传出值} |
买*回*一箱牛奶 |
方法有返回值{不用return返回值, 而用out参数返回值,传出值} |
实例2还可以用以下方法来模拟:
void 逛超市(float 钱, out int 买的东西)
{
//花*出*钱
买的东西= 一箱牛奶;
}
方式3:方式2模拟这件事情用了两个参数,能不能少用一个参数呢。
只用一个参数既起到传入也起到传出值的作用。OK!选用ref 参数
方法构成 |
|
需要花*出*钱 |
方法有参数, 只有一个ref参数{传入值和传出值} |
买*回*一箱牛奶 |
方法有返回值{不用return返回值, 而用ref参数返回值,传出值} |
实例2还可以用以下方法来模拟:
void 逛超市(ref double 钱_买的东西)
{
//花*出*钱
钱_买的东西= 一箱牛奶;
}
四、ref ,out何时用,用在哪里
1、是一种可选的解决方案:
做一件事情,往往有很多方法可以选择,如果一个方法需要返回值,我们可以选择ref或out参数,如上面的例子。
如果只需要方法传出值,选out参数即可
如果需要方法既传入值也传出值,选ref参数
2、是一种最好的解决方案:
比如:某人面试了一家单位,他不但想知道是否要他,还想知道要他或不要他的原因
再如:连接数据库,想知道连接是否成功,如果连接不成功,还想知道不成功的原因
生活中实例多如牛毛:去超市买东西,交给收款员货币,你得到的不仅是要买的物品,还有找零,赠品,,,,
总之,当一个函数需要返回多种不同类型值的时候,往往可以使用ref ,out参数,如
bool Con_DB_Cle(string conStr,ref string why)
{
try
{
//
why="";
return true;
}
catch(Exception e)
{
//
why= e.ToString();
return false;
}
}
五、ref ,out用在哪里,让我们看看类库,类库用的不多啊!!
例子1:System..::.Uri.TryCreate 方法:..:: 使用指定基和相对 Uri 实例创建一个新的 Uri。
如果成功创建了 Uri,则方法返回值为 true;否则为 false。
public static bool TryCreate(
Uri baseUri,
Uri relativeUri,
out Uri result //此方法返回时,包含从 baseUri 和 relativeUri 构造的 Uri
)
public static bool TryCreate(
string uriString,
UriKind uriKind,
out Uri result
)
例子2:
protected override bool System.Data.SqlClient.SqlDataAdapter .GetBatchedRecordsAffected
(int commandIdentifier, out int recordsAffected, out System.Exception error)
六、ref ,out的使用原则【依据VS.NET2008 msdn>.NET Framework 开发人员指南】
方+通过引用传递,也可以作为输出参数传递。
通过值传递参数时,方法获取调用方数据的副本,但不能改变调用方的数据副本。
通过引用传递参数时,方法获取指向调用方数据的指针。此数据与调用方共享。如果方法对引用参数做出更改,则这些更改是对调用方的数据进行的。
使用引用参数时,方法可以使用数据的初始状态。
输出参数与引用参数类似,不同之处在于,输出参数以独占方式用于向调用方返回数据,而引用参数可用于将数据传入方法,也可用于从方法中接收数据。
避免使用输出参数或引用参数。
使用定义输出参数或引用参数的成员需要开发人员理解指针、值类型和引用类型之间的细微差别以及输出参数和引用参数之间的初始化差异。
不要通过引用传递引用类型。
通过引用传递一个对象使方法能够用不同的实例替换该对象。在大多数情况下,方法应使用提供的对象,而不应将其替换。对于此规则,有一些少量的例外(例如,可用于交换引用的方法)。
部分版权所有 2005 Microsoft Corporation。保留所有权利。
部分版权所有 Addison-Wesley Corporation。保留所有权利。
有关设计指南的更多信息,请参见
Krzysztof Cwalina 和 Brad Abrams 编著、Addison-Wesley 于 2005 年出版的“Framework Design Guidelines: Conventions, Idioms, and Patterns for Reusable .NET Libraries”
(《框架设计指南:可重用 .NET 库的约定、术语和模式》)。
七、ref ,out的区别?《经典面试题》
ref ,out的区别? |
简记 |
|
1作用 |
ref参数既可以由方法调用端向方法传入值, 也可以由方法向方法调用端传出值 |
传入传出 |
out 参数不能由方法调用端向方法传入值, 但可以由方法向方法调用端传出值 |
只传出 |
|
2语法 |
ref参数必须在方法调用端初始化 |
先初始化 |
out参数在方法调用端可以不初始化【也可以初始化】 但在方法体内必须初始化 |
后初始化 |