ref和out的区别

最近在许多论坛上看到关于了ref和out的区别,发现解释的都不非常理想。

//如下

方法参数上的 out 方法参数关键字使方法引用传递到方法的同一个变量。当控制传递回调用方法时,在方法中对参数所做的任何更改都将反映在该变量中。 
当希望方法返回多个值时,声明 out 方法非常有用。使用 out 参数的方法仍然可以返回一个值。一个方法可以有一个以上的 out 参数。 
若要使用 out 参数,必须将参数作为 out 参数显式传递到方法。out 参数的值不会传递到 out 参数。 
不必初始化作为 out 参数传递的变量。然而,必须在方法返回之前为 out 参数赋值。 
属性不是变量,不能作为 out 参数传递。 

        方法参数上的 ref 方法参数关键字使方法引用传递到方法的同一个变量。当控制传递回调用方法时,在方法中对参数所做的任何更改都将反映在该变量中。 
若要使用 ref 参数,必须将参数作为 ref 参数显式传递到方法。ref 参数的值被传递到 ref 参数。 
传递到 ref 参数的参数必须最先初始化。将此方法与 out 参数相比,后者的参数在传递到 out 参数之前不必显式初始化。 
属性不是变量,不能作为 ref 参数传递。 

//上面的理解起来非常不好理解。下面的理解起来容易一些。

首先:两者都是按地址传递的,使用后都将改变原来的数值。很多人在论坛上解释说out是按数值传递,是错误的。简单的测试后可以知道out使用也能改变数值的,所以肯定是按照地址传递的。

其次:ref可以把参数的数值传递进函数,但是out是要把参数清空,就是说你无法把一个数值从out传递进去的,out进去后,参数的数值为空,所以你必须初始化一次。这个就是两个的区别,或者说就像有的网友说的,ref是有进有出,out是只出不进。经典!!!

 


自己做了一个小小的测试。

客户端代码:

<%@ Page Language="C#" AutoEventWireup="true" CodeFile="reforout.aspx.cs" Inherits="reforout" %>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
    <title>ref与out的区别的示例</title>
</head>
<body>
    <form id="form1" runat="server">
    <div>
        <asp:Button ID="btnRef" runat="server" Text="参数Ref" OnClick="btnRef_Click" />
        <asp:Button ID="btnOut" runat="server" Text="参数Out" OnClick="btnOut_Click" />
        
    </div>
    </form>
</body>
</html>

服务端代码:

using System;

public partial class reforout : System.Web.UI.Page
{
    /// <summary>
    /// 调用参数为ref的方法
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    protected void btnRef_Click(object sender, EventArgs e)
    {
        int number = 10;
        RefExampleMethod(ref number);
        Response.Write("number = "+number);
    }

    /// <summary>
    /// 调用out参数的方法
    /// </summary>
    /// <param name="sender"></param>
    /// <param name="e"></param>
    protected void btnOut_Click(object sender, EventArgs e)
    {
        int number = 20;
        string str= OutExampleMethod(out number);
        Response.Write(str +":"+number);
    }
    /// <summary>
    /// ref参数
    /// </summary>
    /// <param name="num"></param>
    /// <returns></returns>
    private bool RefExampleMethod(ref int num)
    {
        //ref有进有出
        if (num > 5)
            num = 15;
        else
            num = 1;
        return true;

    }

    private string OutExampleMethod(out int num)
    {
        //注释处不可用用num判断,否则编译不通过,因为out传入的值,out是只出不进
        //if (num > 10)
        //    num = 10;
        //else
            num = 5;
        return "哈哈,这是out参数";
    }
   
}

 

 

总结:1)当调用方法前,必须给ref的参数初始化,out的参数可以初始化,也可以不用初始化

            2)在调用的方法中,必须重新给out初始化值(也就是和out传进来的初始化值无关)

 public int PrintNumber(out int num)

{

   num+=2;//会报错

  必须先给num赋值,再返回

   return num;//会报错

 

   num=3;

   return num;//正确

}

所谓的“只出不进”就是无论给out传入了什么值,在调用的方法中,都会被初始化(即与传入的值无关)



 


### C# 中 `ref` `out` 的区别及使用场景 #### 1. 基本概念 - **`ref`**:表示引用传递,方法可以修改传入的变量,并且该修改会反映到调用方。要求在调用方法之前,变量必须已经初始化[^4]。 - **`out`**:也表示引用传递,但与 `ref` 不同的是,`out` 参数不需要在传递前初始化。方法负责为 `out` 参数赋值,确保在方法结束时,`out` 参数已经被赋予了一个有效的值[^3]。 #### 2. 使用示例 ##### `ref` 示例 ```csharp public static void ModifyWithRef(ref int value) { value = 10; // 修改传入的变量 } static void Main(string[] args) { int a = 5; ModifyWithRef(ref a); // 调用时需要使用 ref 关键字 Console.WriteLine(a); // 输出 10 } ``` ##### `out` 示例 ```csharp public static void GetValues(out int x, out int y) { x = 100; y = 200; } static void Main(string[] args) { GetValues(out int result1, out int result2); // 调用时需要使用 out 关键字 Console.WriteLine($"Result1: {result1}, Result2: {result2}"); } ``` #### 3. 主要区别 - **初始化要求**:`ref` 参数要求在传递给方法之前必须初始化,而 `out` 参数则不需要初始化。 - **用途**:`ref` 通常用于需要方法修改已初始化变量的场景,而 `out` 则用于返回方法的结果,特别是当需要返回多个值时[^3]。 - **方法职责**:对于 `out` 参数,方法有责任为其赋值;而对于 `ref` 参数,方法只是可能对其进行修改。 #### 4. 注意事项 - **方法重载**:不能仅通过 `ref` `out` 区分重载方法,因为编译器将它们视为相同的签名。 - **异步方法**:`ref` `out` 不能用于异步方法(`async`)的参数[^3]。 - **属性传递**:不能直接传递属性作为 `ref` 或 `out` 参数,因为属性可能是计算值,而不是实际的变量。 #### 5. 使用场景 - **`ref`**:适用于需要方法修改已初始化变量的场景,例如交换两个变量的值[^4]。 - **`out`**:适用于需要方法返回多个结果的场景,例如 `TryParse` 方法,它尝试将字符串解析为某种类型,并通过 `out` 参数返回解析结果[^3]。 ```csharp int number; bool success = int.TryParse("123", out number); Console.WriteLine(success ? $"Parsed: {number}" : "Parsing failed"); ``` ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值