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

我知道默认是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(); ... } 

参数是通过值传递的 – 但参数不是对象 ,而是参考 。 该引用正在通过值传递,但是通过该引用对对象所做的任何更改仍将由调用者看到。

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

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

现在,如果你调用InsertLicense(ref foo) ,它将使foo null。 没有参考,它就不会。

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

  • 参数传递C#
  • 引用和值 (值类型和引用类型之间的差异)

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

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

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

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

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

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

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

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

考虑到这一点并认为我应该分享微软所说的:

“不要混淆通过引用传递的概念与引用类型的概念。这两个概念是不一样的。方法参数可以通过ref修改,无论它是值类型还是引用类型。没有拳击通过引用传递的值类型。“

MSDN:ref(C#参考)