C# 在c中,当向方法发送参数时,我们应该在何时使用;参考「;什么时候;“出去”;什么时候没有他们?

C# 在c中,当向方法发送参数时,我们应该在何时使用;参考「;什么时候;“出去”;什么时候没有他们?,c#,methods,parameters,C#,Methods,Parameters,在c#中,当向方法发送参数时,何时应该使用“ref”和“out”以及何时不使用它们?非常简单。您使用的关键字与方法中最初声明参数的关键字完全相同。如果声明为out,则必须使用out。如果声明为ref,则必须使用ref 通常,如果可能,应避免使用ref和out 也就是说,当方法可能需要修改值时,请使用ref。当方法始终应该为值指定某些内容时,使用out ref和out之间的区别在于,当使用out时,编译器强制执行一条规则,即在返回前需要为out参数赋值。使用ref时,在将变量用作ref参数之前,必

在c#中,当向方法发送参数时,何时应该使用“ref”和“out”以及何时不使用它们?

非常简单。您使用的关键字与方法中最初声明参数的关键字完全相同。如果声明为
out
,则必须使用
out
。如果声明为
ref
,则必须使用
ref

通常,如果可能,应避免使用ref和out

也就是说,当方法可能需要修改值时,请使用ref。当方法始终应该为值指定某些内容时,使用out

ref和out之间的区别在于,当使用out时,编译器强制执行一条规则,即在返回前需要为out参数赋值。使用ref时,在将变量用作ref参数之前,必须为其指定一个值

显然,当您编写自己的方法时,上述内容是适用的。如果需要调用在其参数上使用ref或out修饰符声明的方法,则在调用该方法时,应在参数之前使用相同的修饰符


还要记住,C#通过引用传递引用类型(类)(如中所示,引用是通过值传递的)。因此,如果您提供了一个引用类型作为参数的方法,该方法可以修改对象的数据;即使没有ref或out。但是它不能修改引用本身(例如,它不能修改引用的对象)。

它们主要用于从方法调用中获取多个返回值。就我个人而言,我倾向于不使用它们。如果我想从一个方法中得到多个返回值,那么我将创建一个小类来保存它们

ref和out在您希望从该参数中的方法返回某些内容时使用。我记得,它们实际上都编译成同一个IL,但C#放置了一些额外的东西,所以你必须具体一些

以下是一些例子:

static void Main(string[] args)
{
    string myString;
    MyMethod0(myString);
    Console.WriteLine(myString);

    Console.ReadLine();
}

public static void MyMethod0(string param1)
{
    param1 = "Hello";
}
上面的内容不会编译,因为myString从未初始化。如果myString被初始化为string.Empty,那么程序的输出将是一个空行,因为MyMethod0所做的只是将一个新字符串分配给对param1的本地引用

static void Main(string[] args)
{
    string myString;
    MyMethod1(out myString);
    Console.WriteLine(myString);

    Console.ReadLine();
}


public static void MyMethod1(out string param1)
{
    param1 = "Hello";
}
myString没有在Main方法中初始化,但是程序输出“Hello”。这是因为Main方法中的myString引用正在从MyMethod1更新。MyMethod1不希望param1已经包含任何内容,因此可以不初始化它。但是,该方法应该是赋值

static void Main(string[] args)
{
    string myString;
    MyMethod2(ref myString);
    Console.WriteLine(myString);

    Console.ReadLine();
}

public static void MyMethod2(ref string param1)
{
    param1 = "Hello";
}
这同样不会编译。这是因为ref要求首先将Main方法中的myString初始化为某个对象。但是,如果Main方法被更改,myString被初始化为string.Empty,那么代码将被编译,输出将是Hello

因此,差分is out可以用于未初始化的对象,ref必须传递给初始化的对象。如果你传递一个对象时没有任何一个引用,它就不能被替换

需要明确的是:如果正在传递的对象已经是引用类型,那么该方法可以更新该对象,并且更新会反映在调用代码中,但是不能更改对该对象的引用。因此,如果我编写这样的代码:

static void Main(string[] args)
{
    string myString = "Hello";
    MyMethod0(myString);
    Console.WriteLine(myString);

    Console.ReadLine();
}

public static void MyMethod0(string param1)
{
    param1 = "World";
}
程序的输出将是Hello,而不是World,因为该方法只更改了引用的本地副本,而不是传入的引用

我希望这是有道理的。我的一般经验法则就是不要使用它们。我觉得这是对OO之前时代的一种倒退。(但是,这只是我的观点)

(这是对现有答案的补充-一些额外考虑)

还有另一种情况是将
ref
与C#一起使用,这种情况在XNA中更常见。。。通常,当您传递一个值类型(
struct
)时,它会被克隆。这将使用堆栈空间和几个CPU周期,并产生副作用,即对调用的方法中的
struct
的任何修改都将丢失

(旁白:通常
struct
s应该是不可变的,但可变结构在XNA中并不少见)

为了解决这个问题,在这样的程序中经常会看到
ref

但是在大多数程序中(即使用
es作为默认值),通常只需“按值”传递引用即可(即,无
ref
/
输出


out
的另一个非常常见的用例是
Try*
模式,例如:

string s = Console.ReadLine();
int i;
if(int.TryParse(s, out i)) {
    Console.WriteLine("You entered a valid int: " + i);
}
或者类似地,在字典上


这可以使用一个元组来代替,但这是一种非常常见的模式,即使是那些挣扎于太多的
ref
/
out

的人也可以合理地理解它,尽量避免使用ref.out,因为你知道会发生什么,即使函数失败,旧值也将消失,新值将出现在变量中。然而,仅仅通过查看函数,您不知道ref参数会发生什么。它可能是相同的、修改过的或是一个全新的对象


每当我看到ref,我都会感到紧张。

ref是要避免的(我相信这也有一个fx-cop规则),但是当引用的对象本身可能发生变化时,请使用ref。如果您看到'ref'关键字,您就知道在调用方法后,基础对象可能不再被同一变量引用。

除了Colin的详细答案外,您还可以使用out参数从一个方法调用返回多个值。例如,请参见下面返回3个值的方法

static void AssignSomeValues(out int first, out bool second, out string third)
    {
        first = 12 + 12;
        second = false;
        third = "Output parameters are okay";
    }
你可以这样使用它

static void Main(string[] args) {
        int i;
        string s;
        bool b;

        AssignSomeValues(out i, out b, out s);

        Console.WriteLine("Int value: {0}", i);
        Console.WriteLine("Bool value: {0}", b);
        Console.WriteLine("String value: {0}", s);

        //wait for enter key to terminate program
        Console.ReadLine(); }

只需确保为每个out参数指定一个有效值,以避免出错。

我认为odiseh是在编写自己的方法时说的,但我可能错了!科林,非常感谢……但是假设不是使用“param”