2010-03-03 20 views
1

我正在通過該值將一個參數/對象傳遞給函數「RefValTest(object oIn)」,但在函數調用結束之後,由該值傳遞的對象將發生更改,這種情況不會發生,對吧?在c#中傳遞的參數不能如預期那樣工作?使用內部函數反射

class MilanTest 
    { 
     public int SomeValue { get; set; } 
    } 

    class PR 
    { 

     public static object RefValTest(object oIn) 
     { 

     PropertyInfo tProperty = oIn.GetType().GetProperty("SomeValue"); 
     tProperty.SetValue(oIn, 5, null); 

     return null; 
     } 

    } 

主某處:

 MilanTest x = new MilanTest(); 
     //here is by compiler default x.Somevalue == 0 

     PR.RefValTest(x); 
     //here is by compiler default x.Somevalue == 5 

它是如何可能的呼叫後, 「PR.RefValTest(X)」 對象x.SomeValue的值被改變?

Br, 米蘭。

+0

通過值傳遞的對象沒有改變,只改變了它的一個屬性。 – tafa 2010-03-03 11:48:26

+1

@tafa:* object *不會被值傳遞;一個*引用*是按值傳遞的。 – 2010-03-03 11:49:30

回答

2

問題是你混淆了你傳遞的東西,並且「按價值」傳遞一個對象永遠不會起作用。

當你傳遞一個引用類型(任何派生自System.Object的東西)時,你傳遞的是一個參考該對象 - 而不是對象本身。本質上,你傳遞的是存儲對象數據的內存地址。無論您是通過引用還是通過值來傳遞此方法,該方法內部發生的事情是,地址是到您的原始對象。無論您傳遞「指向地址的指針」還是「地址的副本」,地址本身都不會改變。

因此,無論您如何傳遞該類型,您都會發現原始對象是您正在修改的內容。如果你真的需要這個功能,你可以選擇創建一個對象的克隆,然後傳入克隆(或者讓你的方法自己創建克隆)。這樣克隆被修改而不是原來的對象。

+0

Hi Dan,Thorsten,Jon, 你們都回答了我的問題,但Dan Puzey更詳細地解釋了它!謝謝大家 ! – Milan 2010-03-03 12:22:34

+0

@Milan:在這種情況下,我讓鏈接的文章給出了更多細節 - 這些年來我花了很多時間寫這篇文章;)(我絕不建議你改變接受的答案,但請如果你有任何懷疑,請閱讀那篇文章。) – 2010-03-03 12:45:46

0

您不能更改引用oIn但您可以更改其屬性。

你的方法裏面

所以,如果你在外面說

oIn = "SomeString"; 

你不會看到這一點。

2

非常簡單:傳遞到該方法的是參考到對象。然後您將更改該對象內的數據。所以當你再看這個對象時,你可以看到變化。

你不需要使用反射來看看這方面的工作 - 這裏是你的代碼的簡化版本:

class MilanTest 
{ 
    public int SomeValue { get; set; } 
} 

class Test 
{ 
    static void RefValTest(MilanTest x) 
    { 
     x.SomeValue = 5; 
    } 

    static void Main() 
    { 
     MilanTest t = new MilanTest(); 
     RefValTest(t); 
     Console.WriteLine(t.SomeValue); // Prints 5 
    } 
} 

詳情請參閱my article on parameter passing

+2

此外,當傳遞參數爲「ref object oIn」時,您也可以更改引用本身。這意味着「oIn = someOtherObject」會(在你的示例中)使「x」成爲另一個對象。 – 2010-03-03 11:50:18

0

錯了。這應該發生,無論你直接設置值或繞道而行。這就是通過引用傳遞的意思:您正在與同一對象實例進行交互,而不是副本。

+0

除*這不是*通過引用傳遞,它是按值傳遞引用。 – 2010-03-03 11:49:12

+0

Nitpick接受... – 2010-03-03 11:55:05

+0

你可以稱它爲「挑剔」,但它是一個重大混淆的來源,尤其是C#*具有'ref'具有適當的引用傳遞語義。 – 2010-03-03 12:13:36

相關問題