2011-03-11 30 views
7

我有暴露的Arraylist以下公共財產:屬性 - 按值或引用?

public ArrayList SpillageRiskDescriptions 
     { 
      get 
      { 
       return _SpillageRiskDescriptions; 
      } 
      set 
      { 
       _SpillageRiskDescriptions = value; 
      } 
     } 

在其他地方我打電話

SpillageRiskDescriptions.Add("VENTILATE AREA"); 
SpillageRiskDescriptions.Add("DO NOT ALLOW SPILLAGE TO ENTER MAINS"); 

這些似乎將元素添加到私人的ArrayList _SpillageRiskDescriptions(通過屬性)而我會預料到這會導致一個問題。因此,我正確地認爲屬性將參考返回到原始變量,並且不通過?這是因爲ArrayList是參考類型嗎? int(例如?)

回答

9

從技術上講,它始終是有價值的,但你必須明白傳遞的是什麼。由於它是一個引用類型,所以你傳遞了一個引用(但是通過值)。

希望是有道理的。您總是將結果傳回給值,但如果類型是引用,則您將引用通過值傳遞回來,這意味着您可以更改該對象,但不能更改該引用的對象。

+2

想象它與C++一樣,你可以將一個指針傳遞給一個對象,並且你可以改變那個指針指向的內容,但是你不能指向其他東西,因爲你有一個指針的副本而不是原始指針。如果你想改變它指向的對象,你必須傳遞一個指針指向一個指針(或者指向一個指針)。這就是爲什麼在C#中,如果要更改引用的對象,則需要ref和out關鍵字。 – 2011-03-11 15:31:51

+0

非常好 - 這非常有用 – 2011-03-11 15:35:27

1

它是否與財產本身無關;它是屬性的數據類型。在這種情況下,您使用的是ArrayList,它是通過引用傳遞的類。如果該房產被輸入爲int,則將按價值傳遞。

2

C#通過引用返回對象。

只有值不能返回的東西是:

原始類型。
結構類型。
枚舉。

+0

本質上是真實的,儘管從技術上講,它通過值傳回對象引用。 – 2011-03-11 15:33:54

+0

另外C++指針是按值傳遞的,但是這是通過引用定義的。傳遞對象的地址而不是對象本身。 – 2011-03-11 16:15:15

0

屬性實際上是一對兩個方法 - 一個setter和一個getter。它們傳遞後臺字段的值(或任何用作源/目標的值)。因此,對於引用類型,引用被傳遞,對於值類型,傳遞值。

// this is how the getter method looks like 
public ArrayList get_SpillageRiskDescriptions() 
{ 
    return _SpillageRiskDescriptions; 
} 

// this is how the setter method looks like 
public void set_SpillageRiskDescriptions(ArrayList value) 
{ 
    _SpillageRiskDescriptions = value; 
} 

注意,通過分配ArrayList實例爲你的財產,你基本上更換ArrayList例如,通過支持字段指向。

爲了回答您的具體問題:

所以我在想糾正屬性返回一個參考給原來的變量,而不是由傳遞呢?

不,通過使用getter,您不會獲得對_SpillageRiskDescriptions字段的引用。您會得到該字段的,該字段是對(動態分配的)實例的引用。

這是因爲ArrayList是引用類型嗎?

是的,ArrayList是一個參考類型,因此您會收到對特定ArrayList實例的引用。

同樣會發生int(例如?)

是和否。 是的,您將收到一個int字段的值。並且,int是一個值類型,所以如果您修改該值而不明確地將其設置回來,則基礎字段將不受影響。

0

它沒有任何與財產。

在這種情況下,您正在按值傳遞對數組列表的引用。

如果你這樣做

 void AddSomethingToArrayList(ArrayList spillageRiskDescriptions){ 
      spillageRiskDescriptions.Add("Something"); 
     } 

則引用數組列表將被修改。

如果你做這樣的事情

 void ReassignArrayList(ArrayList spillageRiskDescriptions){ 
      spillageRiskDescriptions = new ArrayList(); 
      spillageRiskDescriptions.Add("Something"); 
     } 

那麼原來的參照數組列表將不會發生任何變化。

但是,如果你是通過引用傳遞的參考,如:

 void ReassignArrayListByRef(ref ArrayList spillageRiskDescriptions){ 
      spillageRiskDescriptions = new ArrayList(); 
      spillageRiskDescriptions.Add("Something"); 
     } 

那麼你的財產將結束與一個單一的項目一個新的數組列表。

7

其他的答案都正確地回答了你的首要問題:是引用類型的屬性參考的引用類型的實例

更大的問題是「現在你對此做了什麼?想必你不是想要的代碼,可以獲得該清單能夠更改它。

這裏有幾個選項。

首先,不管你做什麼,我建議你現在停止使用ArrayList,並開始使用更現代,安全的類型來存儲事物列表。 List<string>立即想起來。

二,是否有必要將該物業的籌款人公開?你想只有任何人能夠改變這個列表嗎?還是應該類型本身負責以某種方式更新它?我會考慮讓制定者保密。

第三,對於「微不足道」的屬性,我們有更緊湊的語法。您可能會說

public List<string> SpillageListDescriptions { get; private set; } 

並且編譯器會爲您生成後備字段。

請注意,List<string>仍然允許突變。

如果所有的客戶關心的是能夠同時遍歷列表中的一個東西,那麼你可以這樣做:

private List<string> descriptions = whatever; 
public IEnumerable<string> SpillageListDescriptions 
{ 
    get 
    { 
     if (descriptions == null) yield break; 
     foreach(var description in descriptions) 
      yield return description; 
    } 
} 

,現在是不可能的呼叫者變異的名單,因爲你給它們的只是一個迭代器,而不是訪問列表本身。

或者你可以這樣做:

private List<string> descriptions = whatever; 
public IList<string> SpillageListDescriptions 
{ 
    get 
    { 
     return new ReadOnlyCollection<string>(descriptions); 
    } 
} 

而且現在的調用者,如果他們試圖去修改它會拋出一個異常列表的只讀視圖。

+0

非常感謝您的反饋,但是其中大部分內容(短屬性語法和帶有公共getter的私有setter)僅在框架的更高版本中可用 - 我正在使用.NET2。我實際訪問的原因是,我可以將ArrayList轉換爲列表。然而,它很好找出我在做什麼是對的。 – 2011-03-11 16:01:22

+0

他提到的唯一解決方案在.Net 2中不可用,它是自動屬性,可以在.Net 2中手工實現。你還需要用'string'替換'var'。 – Brian 2011-03-14 13:16:50

相關問題