如何更改方法中的变量并在外部更改它

时间:2018-05-22 17:16:19

标签: c#

我有一个变量,我想在函数内部进行更改,并反映原始变量中的新变化。我试图在函数内部将原始变量值更改为Scott,然后在函数外反映出新的更改:

public ActionResult HomePage()
{
  string name = "John";
  ChangeName(name);
  string newName = name ; -- This still says John
}

public static void ChangeName(string myname)
{
  myname = "Scott";
}

2 个答案:

答案 0 :(得分:6)

您可以通过引用 -

传递字符串来实现
public ActionResult HomePage()
{
    string name = "John";
    ChangeName(ref name);
    string newName = name ; -- This is now Scott.
}

public static void ChangeName(ref string myname)
{
  myname = "Scott";
}

但是,正如TheSoftwareJedi在评论中所述,通常最好避免通过引用传递参数。相反,你应该让你的方法返回新的字符串,特别是考虑到字符串是不可变的,所以你不能真正改变它们,你只能改变引用指向另一个字符串。

所以更好的方法是这样的:

public static string GetAnotherName()
{
  return "Scott";
}

更深入一点 - 在c#中基本上有两种类型(至少与这一点相关):有值类型,如枚举,结构(包括所有基本类型,如int,bool等' )并且有参考类型(基本上,其他一切)。

无论何时将参数传递给方法,它都会按值传递,除非您指定ref(或out)关键字,即使它是引用类型(在这种情况下) ,引用按值传递)。这意味着当您为方法内的参数分配新值时,如果参数通过引用显式传递(使用refout关键字),您将只在方法外部看到它

引用类型和值类型之间的主要区别在于,当您在方法中更改引用类型的属性时,您将在方法外部看到新值,但是当您更改内部值类型的属性时一种方法,该变化不会反映到该方法之外的变量。

Jon Skeet写了fairly extensive article about that subject,他在解释事情方面比我好,所以你也应该阅读它。

答案 1 :(得分:1)

首先,我建议您阅读有关引用,值和参数传递的信息。 Jon Skeet对此主题进行了很好的总结 - Parameter passing in C#以及Eric Lippert对参考概念的良好解释 - References are not addresses

你应该知道默认情况下,参数是通过C#中的值传递的,这意味着参数将包含作为参数传递的引用的副本,这意味着赋值只会更改参数本身,并且在调用站点处不会被观察到。

这就是为什么

myname = "Scott";

仅更改方法参数myname的值,而不更改外部name变量。

同时,我们可以使用refinout关键字通过引用传递我们的变量。虽然inout关键字正在添加超出主题的超额保证,但我将继续使用ref

您应该更改方法的声明并调用网站以使用它。

public static void ChangeName(ref string myname)
{
    myname = "Scott";
}

它应该现在作为

调用
ChangeName(ref name);

这次没有复制,因此myname参数存储与name变量相同的引用,而且参数和变量存储在一个位置,这意味着更改为myname内部调用代码时可以看到ChangeName方法。

要继续,我想就您的问题 - ExpressionsStatements指出一个单独但相关的主题,并将您链接到一篇关于他们的好文章。 Scott Wlaschin - Expressions vs statements(里面有一些F#,但这并不重要)。

通常情况下,您选择的方法没有任何问题,但这是必要的,基于陈述的,有点太低级别。您被迫处理引用及其值,而您真正想要的只是从您的方法中获得值“Scott”。如果实现为表达式,这将看起来更直接和明显。

public static string GetName() => "Scott";

这种方式代码是声明性的,因此更简单(和简短),它直接说明了你的目标。