我正在创建一个函数,我需要传递一个对象,以便它可以被函数修改。有什么区别:

public void myFunction(ref MyClass someClass)

and

public void myFunction(out MyClass someClass)

我应该用哪个,为什么?


当前回答

除了允许你将别人的变量重新分配给类的不同实例,返回多个值等,使用ref或out可以让别人知道你需要从他们那里得到什么,以及你打算用他们提供的变量做什么

You don't need ref or out if all you're going to do is modify things inside the MyClass instance that is passed in the argument someClass. The calling method will see changes like someClass.Message = "Hello World" whether you use ref, out or nothing Writing someClass = new MyClass() inside myFunction(someClass) swaps out the object seen by the someClass in the scope of the myFunction method only. The calling method still knows about the original MyClass instance it created and passed to your method You need ref or out if you plan on swapping the someClass out for a whole new object and want the calling method to see your change Writing someClass = new MyClass() inside myFunction(out someClass) changes the object seen by the method that called myFunction

还有其他程序员

他们想知道你将如何处理他们的数据。假设您正在编写一个将被数百万开发人员使用的库。你想让他们知道当他们调用你的方法时你要对他们的变量做什么

Using ref makes a statement of "Pass a variable assigned to some value when you call my method. Be aware that I might change it out for something else entirely during the course of my method. Do not expect your variable to be pointing to the old object when I'm done" Using out makes a statement of "Pass a placeholder variable to my method. It doesn't matter whether it has a value or not; the compiler will force me to assign it to a new value. I absolutely guarantee that the object pointed to by your variable before you called my method, will be different by the time I'm done

顺便说一下,在c# 7.2中也有一个in修饰符

And that prevents the method from swapping out the passed in instance for a different instance. Think of it like saying to those millions of developers "pass me your original variable reference, and I promise not to swap your carefully crafted data out for something else". in has some peculiarities, and in some cases such as where an implicit conversion might be required to make your short compatible with an in int the compiler will temporarily make an int, widen your short to it, pass it by reference and finish up. It can do this because you've declared you're not going to mess with it.


微软对数值类型的.TryParse方法做到了这一点:

int i = 98234957;
bool success = int.TryParse("123", out i);

通过将参数标记为out他们在这里积极地声明"我们肯定会将你苦心制作的98234957值更改为其他值"

当然,对于像解析值类型这样的事情,它们有点不得不这样做,因为如果parse方法不允许将值类型替换为其他类型,那么它就不能很好地工作。但是想象一下在你创建的库中有一些虚构的方法:

public void PoorlyNamedMethod(out SomeClass x)

你可以看到它是一个out,因此你可以知道,如果你花了几个小时处理数字,创建一个完美的SomeClass:

SomeClass x = SpendHoursMakingMeAPerfectSomeClass();
//now give it to the library
PoorlyNamedMethod(out x);

那真是浪费时间,花那么多时间来做一节完美的课。它肯定会被丢弃,并被PoorlyNamedMethod取代

其他回答

Ref和out的行为类似,只是有一些不同。

引用变量必须在使用前初始化。Out变量无需赋值即可使用 Out形参必须被使用它的函数视为未赋值。因此,我们可以在调用代码中使用初始化的out形参,但该值将在函数执行时丢失。

注意,在函数内部传递的引用参数是直接处理的。

例如,

    public class MyClass
    {
        public string Name { get; set; }
    }

    public void Foo()
    {
        MyClass myObject = new MyClass();
        myObject.Name = "Dog";
        Bar(myObject);
        Console.WriteLine(myObject.Name); // Writes "Dog".
    }

    public void Bar(MyClass someObject)
    {
        MyClass myTempObject = new MyClass();
        myTempObject.Name = "Cat";
        someObject = myTempObject;
    }

这会写狗,而不是猫。因此,您应该直接在someObject上工作。

下面是一个同时使用Ref和out的例子。现在,你们都可以离开裁判了。

在下面提到的例子中,当我注释//myRefObj = new myClass {Name = "ref outside called!! ""}; 行,将得到一个错误说“使用未分配的局部变量'myRefObj'”,但没有这样的错误在out。

在哪里使用Ref:当我们调用带有in形参的过程时,该形参将用于存储该过程的输出。

在哪里使用Out:当我们调用一个没有in形参的过程时,相同的参数将用于返回该过程的值。 还要注意输出

public partial class refAndOutUse : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        myClass myRefObj;
        myRefObj = new myClass { Name = "ref outside called!!  <br/>" };
        myRefFunction(ref myRefObj);
        Response.Write(myRefObj.Name); //ref inside function

        myClass myOutObj;
        myOutFunction(out myOutObj);
        Response.Write(myOutObj.Name); //out inside function
    }

    void myRefFunction(ref myClass refObj)
    {
        refObj.Name = "ref inside function <br/>";
        Response.Write(refObj.Name); //ref inside function
    }
    void myOutFunction(out myClass outObj)
    {
        outObj = new myClass { Name = "out inside function <br/>" }; 
        Response.Write(outObj.Name); //out inside function
    }
}

public class myClass
{
    public string Name { get; set; }
} 

Ref表示Ref参数中的值已经设置,方法可以读取和修改它。 使用ref关键字等同于说调用方负责初始化形参的值。


Out告诉编译器,对象的初始化是由 函数需要赋值给out形参。 没有分配是不允许的。

https://www.codemaggot.com/ref-and-out-keywords/

裁判上场又出局。

您应该优先使用out,只要它能满足您的需求。