2012-03-15 35 views
14

我知道默认值是C#中的ByVal。我在很多地方使用了相同的变量名称,然后我发现传递的值发生变化并返回。我想我知道C#的范围机制错了。这里公开许可证覆盖当地的许可证值。我知道我可以轻松地重命名冲突中的变量名,但我想了解有关范围的事实。C#默认传递参数是ByRef而不是ByVal

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

回答

51

的争论正在按值传递 - 但参数不是对象,这是一个参考参考正在通过值传递,但通过该引用对对象所做的任何更改仍将被调用者看到。

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

现在,如果你调用InsertLicense(ref foo),它将使foo空算账:

这一引用,在这里改变参数本身如这是真正通很大的不同。没有裁判,它不会。

欲了解更多信息,请参阅两篇文章,我写:

+0

行得通吧我以为它已被复制。 – 2012-03-15 09:42:53

3

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

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

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

+0

哈!当然,Jon Skeet击败了我。 – nietras 2012-03-15 09:38:39

+0

不要调用引用“指针”。他们是完全不同的动物! – 2012-03-15 09:40:04

+0

我知道,但为了解释这一点,我认为这是最清楚的,这也是为什么我把它放在引号中。 – nietras 2012-03-15 09:52:45

1

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

1

您正在通过值传递许可证参数;基本上这意味着你可以修改对象的任何公共属性。但是,如果分配到许可对象的引用到一个新的对象,也就是说,如果你这样做:

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

主叫不会引用静态方法中定义的新的许可对象,除非你通过裁判通过它。

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

0

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

“不要混淆引用传递引用类型的概念,这个概念的两个概念是不一样的方法的参数即可。由ref修改,无论它是一个值类型还是一个引用类型。当通过引用传递时,没有值类型的装箱。

MSDN: ref (C# Reference)