c#中的ref用法

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c#中的ref用法相关的知识,希望对你有一定的参考价值。

可以理解为类似的传址引用,同时还有out。

在函数需要外部传入一个变量名,然后在程序内部可以将这个值进行修改,典型的传址引用!在定义时必要加ref或out说明!

public void MethodA(out string s )

s = "1";


调用时,应该先声明一个字符变量。

string temp;
MethodA(out temp);
此时可以打印temp的值会变作"1";

而ref与out基本是类同的,如果在程序中引用原值的话,必须使用ref防止传入未初始化的值。
public void MethodB(ref int s)

s = s*s;

因为该函数要使用形参的原值,所以这里必须使用ref声明,不要使用out声明。
使用时,
int temp = 8;
MethodB(ref temp);
打印temp的值会变为64。
ref因为对原值进行了引用,所以ref要求传入的一定是一个初始化后的值,不能是未初始化的值。

int temp;
MethodB(ref temp);
//原则上这样是会错的,但这里我使用了一个int,由于在声明时int temp与int temp =0 是等价的,所以不会出错,但如果是字符串,使用这种方式完全是可以报错的!因为string temp与string temp ="";是不等价的,你也可理解为必须赋值后才可以使用。

public void MethodC(ref string s)

.......


string temp;
MethodC(ref temp);//这种就是错误的方式。ref要求必须形参已经赋值(初始化)。
string temp = "";
MethodC(ref temp);//这种方式就是正确的。

我们定义成员方法时,如果有引用原值使用必须使用ref,防上对方传入一个未初始化的值,引发程序错误,而没有必要对形参的值有要求时,则尽量使用out,防止调用时增加客户端代码量。
希望能解决您的问题。
参考技术A void fun(ref int a)
a+=1;



int i=2;
fun(ref i);
//i=3

在 C# 中使用“ref”关键字 [重复]

【中文标题】在 C# 中使用“ref”关键字 [重复]【英文标题】:Use of 'ref' keyword in C# [duplicate] 【发布时间】:2011-06-16 07:17:07 【问题描述】:

可能的重复:Why use ref keyword when passing an Object?When to pass ref keyword in

C# 中“ref”关键字的正确用法是什么。我相信已经有很多关于此的讨论线程,但我不清楚的是:

    如果要传入引用对象,是否需要 ref 关键字?我的意思是当你在堆中创建一个对象时,它并不总是通过引用传递。这是否必须明确标记为参考?

【问题讨论】:

大量重复...Why use ref keyword when passing an Object?、C# ref keyword usage、When to pass ref keyword in、When is using the C# ref keyword ever a good idea? 等。所有这些似乎都回答了您的问题。有没有他们没有解决的数字 2? 还必须阅读我们自己的 Jon Skeet 关于该主题的文章:Parameter passing in C#。不幸的是,我不能投票关闭作为该副本的副本。 ;-) 【参考方案1】:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;

namespace InOutRef

    static class InOutRef
    
        public static void In(int i)
        
            Console.WriteLine(i);
            i=100;
            Console.WriteLine(i);
        
        public static void Ref(ref int i)
        
            Console.WriteLine(i);
            i=200;
            Console.WriteLine(i);
        
        public static void Out(out int i)
        
            //Console.WriteLine(i); //Error Unsigned Ref
            i=300;
            Console.WriteLine(i);
        
    

    class Program
    
        static void Main(string[] args)
        
            int i = 1;
            InOutRef.In(i); //passed by value (in only)
            Debug.Assert(i==1);
            InOutRef.Ref(ref i); //passed by ref (in or out)
            Debug.Assert(i == 200);
            InOutRef.Out(out i); //passed by as out ref (out only)
            Debug.Assert(i == 300);
        
    

我的回答不能再直白了。当使用 in 时,代码将不会记住引用更改,例如经典的 Java 交换 question。但是,当使用 ref 时,它将类似于 VB.NET,因为它会记住 inout 的变化。如果您使用 out 参数,则意味着必须在返回之前声明它(这是由编译器强制执行的)。

输出: 1 //1 来自主 100 //100 来自 in 1 //1 不会从 In 中记住 200 //200 来自参考 //此处应为 200,但 out 强制输出参数(未打印,因为已注释掉) 300 //300 只出 按任意键继续 。 . .

【讨论】:

【参考方案2】:

这里的答案中有很多令人困惑的错误信息。理解这一点的最简单方法是放弃“ref”意味着“通过引用”的想法。更好的思考方式是“ref”的意思是“我希望被调用方的这个形式参数成为调用方特定变量的别名”。

当你说

void M(ref int y)  y = 123; 
...
int x = 456;
M(ref x);

也就是说“在调用 M 期间,被调用方的形参 y 是调用方变量 x 的另一个名称”。将 123 分配给 y 与将 123 分配给 x 完全相同,因为它们是同一个变量,一个有两个名称的变量。

就是这样。不要考虑引用类型或值类型或其他任何东西,不要考虑按引用传递或按值传递。所有“ref”的意思是“暂时为这个变量命名”。

【讨论】:

【参考方案3】:

使用ref 表示将引用 传递给函数。

默认行为是函数接收对同一对象的新引用。这意味着如果您更改引用的值(例如,将其设置为新对象),那么您将不再指向原始的源对象。当您使用 ref 传递时,更改引用的值会更改源引用 - 因为它们是相同的。

考虑一下:

public class Thing

    public string Property get;set;


public static void Go(Thing thing)

    thing = new Thing();
    thing.Property = "Changed";


public static void Go(ref Thing thing)

    thing = new Thing();
    thing.Property = "Changed";

然后如果你运行

var g = new Thing();

// this will not alter g
Go(g);

// this *will* alter g
Go(ref g);

【讨论】:

+1 最后,一个正确的答案。把这样的问题留得太久是很危险的,因为那里有太多的错误信息。很高兴在这里使用除反对票以外的其他东西。 害怕有人反对这个;我不想和那个人一起工作! 可能有人对这里给出的答案的大量反对票感到不安。这是我没有尝试提供自己的主要原因。更糟糕的是想象与仍然在 cmets 中尝试和争论的人一起工作。【参考方案4】:

我相信 ref 关键字表明您通过引用而不是值传递对象。例如:

void myfunction(ref object a) 
a = new Something();

会改变调用函数中a的值 不过,

void myfunction(object a) 
a = new Something();

将在本地更改 a 的值,但不会在调用函数中更改。您仍然可以更改项目的属性,但不能设置项目本身的值。例如; a.someproperty = value;

在这两种情况下都可以使用。

【讨论】:

第二个例子(没有 ref)将无法编译,因为这就像说 1 = 3。1 不可能等于 3。但是,使用 ref。好像在说。 x = 1。然后 x = 3。 第二个例子会“工作”,但可能会产生意想不到的结果! 我猜它编译,但它不会改变调用函数上下文中 a 的值。 在对a 的引用在本地成功重新分配的意义上是可行的。但这种变化不会反映回调用函数。它肯定不会导致编译时错误。

以上是关于c#中的ref用法的主要内容,如果未能解决你的问题,请参考以下文章

C#中的const形参

C# ref out parase 理解

C# out ref 用法总结

C# 中的三个高级参数 ref

P17:React高级-ref 的用法和 ref 中的坑

C#值参数和引用参数,方法的重载,foreach,数组,以及ref和out的用法