C#默认传递参数是ByRef而不是ByVal

时间:2012-03-15 09:33:37

标签: c#

我知道默认是C#中的ByVal。我在很多地方使用了相同的变量名,然后我注意到传递的值改变了并且回来了。我想我知道C#的范围机制是错误的。此处公开许可会覆盖本地许可值。我知道我可以很容易地重命名冲突中的变量名称,但我想了解有关范围的事实。

  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();
        ...
     }

5 个答案:

答案 0 :(得分:58)

参数是通过值传递的 - 但参数不是对象,它是引用引用正在按值传递,但调用者仍会看到通过该引用对对象所做的任何更改。

这与真实通过引用传递非常不同,其中对参数本身的更改如下:

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

现在,如果您致电InsertLicense(ref foo),之后会foo为空。没有参考,它就不会。

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

答案 1 :(得分:3)

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

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

虽然,不一定正确,值类型通常在堆栈上或引用类型中分配。虽然引用类型始终在托管堆上分配。

答案 2 :(得分:2)

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

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

除非您通过ref。

传递,否则调用者不会引用静态方法中定义的新许可证对象

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

答案 3 :(得分:1)

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

答案 4 :(得分:0)

跑过这个,并认为我应该分享微软所说的:

"不要将引用传递的概念与引用类型的概念混淆。这两个概念不尽相同。无论是值类型还是引用类型,都可以通过ref修改方法参数。通过引用传递时,没有值类型的装箱。"

MSDN: ref (C# Reference)