2012-02-16 78 views
1

比方說,我有對象的列表和我解壓,然後從列表這樣的修改項目:C#通過引用或值

List<MyObject> TheListOfObjects = new List<MyObject>(); 
MyObject TheObject = new MyObject(); 

TheListOfObjects = //some json deserialization result 

TheObject = (from o in TheListOfObject 
      where o.ID == SomeParameter 
      select o).SingleOrDefault(); 

TheObject.SomeProperty = SomeValue; 

當我寫TheObject.SomeProperty = SomeValue;我是:

  1. 修改列表中的項目,在這種情況下,我完成或
  2. 修改一個新的項目,我必須用我剛剛修改的項目替換列表中的原始項目。
+5

您已經編寫了代碼;嘗試一下,看看會發生什麼! – 2012-02-16 15:05:39

+1

我不明白你爲什麼要創建* new *對象,然後通過將新實例分配給變量來拋出它們? – 2012-02-16 15:14:36

+0

@EricLippert:有時候事情是偶然發生,然後停止工作,我只是想澄清一下,我得到的真的是我想要的。你在書中讀到byval vs byref,但實際上你確實在學習。 – frenchie 2012-02-16 15:33:59

回答

6

取決於。

如果對象列表是一個類實例列表,則TheObject變量將保存一個值參考。該參考也將在列表中存在。在該參考中的對象的修改將在兩者中都可見。重要提示:在變量中包含的引用(即變量重新分配)上的寫作不會保留到列表中,也不會在列表中的引用上繼續寫入變量。

如果對象列表是結構實例列表,則TheObject只包含,並且該值的突變在列表內不可見。

+0

爲什麼有人會在類上使用結構? – frenchie 2012-02-16 15:08:47

+1

因爲有時結構語義(byval copy和成員比較)正是你所需要的。 – GSerg 2012-02-16 15:09:20

+0

@frenchie,看到[這個相關的問題](http://stackoverflow.com/questions/85553/when-should-i-use-a-struct-instead-of-a-class) – 2012-02-16 15:11:04

1

您正在修改列表中的項目,因爲調用返回對列表中項目的引用,而不是其副本。而且,對象你

MyObject TheObject = new MyObject(); 

創建只是扔掉,因爲你改變了參照新選擇的項目。你可以省略這行,只是做:

MyObject theObject = (from o in TheListOfObject 
     where o.ID == SomeParameter 
     select o).SingleOrDefault(); 

我假設的MyObject是一個類,而不是一個結構,因爲我們正在與操作變異它,mutable structs are evil

1

在項目的列表是通過引用保存的,所以你修改同一個對象 - 不需要嘗試將它複製回列表中,因爲它已經在那裏。

1

您正在修改的項目列表中的TheObject參考到內存中的唯一項目。

你甚至可以創建多個列表,所有列表將包含在內存中,相同的對象引用。


也有一些是你的代碼錯誤:

MyObject TheObject = new MyObject(); 

... 

TheObject = (from o in TheListOfObject 
      where o.ID == SomeParameter 
      select o).SingleOrDefault(); 

你是第一個創建對象的新實例,將影響到TheObject一個新值。

代碼的= new MyObject();一部分是無用的。相同= new List<MyObject>();

+0

我想我覺得在函數的開頭聲明所有的變量對我來說更具可讀性;我在做這件事的方式會對性能產生影響嗎?替代方案可以是MyObject TheObject = null;這樣更好嗎? – frenchie 2012-02-16 18:46:00

+0

@frenchie通常不推薦在C#中在方法的開始部分聲明變量(在C中爲true,但不在C#中)。通常最好將變量**聲明爲儘可能接近它們的用法**。也就是說,如果你真的想在你的函數開頭聲明變量,那麼'MyObject TheObject = null;'比MyObject TheObject = new MyObject();''MyObject TheObject''好得多。 – ken2k 2012-02-16 19:59:44

+0

好吧,我會用= null在我的代碼中進行一些更改;謝謝。 – frenchie 2012-02-17 00:19:53

5

這就要看MyObject是否是一個類或結構。

如果它是一個類,那麼您正在修改原始對象。
如果它是一個結構體,你正在修改一個副本。

+0

爲什麼有人會使用結構班? – frenchie 2012-02-16 15:08:22