【问题标题】:C# Passing arguments by default is ByRef instead of ByValC# 传递参数默认是 ByRef 而不是 ByVal
【发布时间】:2021-11-08 06:04:20
【问题描述】:

我知道默认值是 C# 中的 ByVal。我在很多地方使用了相同的变量名,然后我注意到传递的值发生了变化并回来了。我想我知道 C# 的作用域机制是错误的。这里公共 license 覆盖本地 license 值。我知道我可以轻松地重命名冲突的变量名,但我想了解有关范围的事实。

  public static class LicenseWorks
  {
     public static void InsertLicense(License license)
     {
        license.registered = true;
        UpdateLicense(license);
     }
  }

  public partial class formMain : Form
  {
     License license;

     private void btnPay_Click(object sender, EventArgs e)
     {
          license.registered = false;
          LicenseWorks.InsertLicense(license);

          bool registered = license.registered; //Returns true!
      }
  }    

更新:我在下面添加了解决方案:

    public static void InsertLicense(License license)
    {

        license = license.Clone();
        ...
     }

【问题讨论】:

  • 虽然我完全同意 gt6707a,但我还没有什么声誉可以评论。在那之前的答案,有条件地是有意义的,如果我们给窗帘词\短语赋予窗帘含义(比如 - “它是按值传递的......”意味着“引用是从新的”),那将是不寻常的。事实上,即使明确提及,引用类型也不是按值传递的。就是这样。

标签: c#


【解决方案1】:

参数是按值传递的——但参数不是一个对象,它是一个引用。该 reference 是按值传递的,但是调用者仍然可以看到通过该引用对 object 所做的任何更改。

这与真正的通过引用传递非常不同,其中参数本身的变化如下:

 public static void InsertLicense(ref License license)
 {
    // Change to the parameter itself, not the object it refers to!
    license = null;
 }

现在如果你调用InsertLicense(ref foo),它会在之后使foo为空。没有 ref,它就不会。

有关详细信息,请参阅我写的两篇文章:

【讨论】:

  • 好的,我以为它被复制了。
  • 精彩,易于理解,并且(至少对我而言)具有启发性。不错的答案!你应该为此写一本书;-)
【解决方案2】:

您需要了解引用类型值类型之间的区别。在这里,我假设您使用的是引用类型许可证,这意味着您实际上是在解析 reference 到相关实例。

见:http://msdn.microsoft.com/en-us/library/aa711899(v=vs.71).aspx

虽然,不一定正确的值类型通常分配在堆栈上或引用类型内。而引用类型总是分配在托管堆上。

【讨论】:

  • 不要将引用称为“指针”。它们是完全不同的动物!
  • 我知道,但是为了说明这里的意思,我认为它最清楚,这也是我把它放在引号中的原因。
【解决方案3】:

您正在按值传递许可参数;本质上,这意味着您可以修改对象的任何公共属性。但是,如果您将许可证对象的引用重新分配给一个新对象,即如果您这样做:

public static void InsertLicense(License license)      
{         
   license = new Licence();         
   UpdateLicense(license);      
}

调用者不会引用静态方法中定义的新许可对象,除非您通过 ref 传递它。

请记住,除非您使用 ref 或 out 关键字,否则所有参数都是按值传递给方法的。

【讨论】:

    【解决方案4】:

    在 InsertLicense 中传递许可证时,您不是按值传递,而是作为参考传递。 这意味着当将注册项更改为 true 时,它​​会更改它,并且在返回引用后注册项将为 true。

    【讨论】:

      【解决方案5】:

      遇到这个,我想我应该分享一下微软所说的:

      "不要把引用传递的概念和引用类型的概念混为一谈,这两个概念是不一样的。一个方法参数可以通过ref来修改,不管是值类型还是引用类型。有是通过引用传递时没有值类型的装箱。”

      MSDN: ref (C# Reference)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-01-02
        • 2010-09-29
        • 2020-06-30
        • 2018-03-11
        • 2010-11-17
        • 2016-05-12
        • 1970-01-01
        • 2019-04-11
        相关资源
        最近更新 更多