2012-03-15 38 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)