我知道默认是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();
...
}
答案 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修改方法参数。通过引用传递时,没有值类型的装箱。"