2011-08-19 132 views
14

我在列表中有一個用戶定義的結構,我試圖改變結構列表中單個元素的值。訪問元素不是問題。然而,當我嘗試更新的值,編譯器會抱怨:如何爲VB.NET中的列表中的結構元素賦值?

「表達式是一個值,因此不能成爲 賦值的目標」

例如:

Public Structure Person 

    Dim first as String 
    Dim last as String 
    Dim age as Integer 

End Structure 

_

Public Sub ListTest() 

    Dim newPerson as Person 

    Dim records as List (Of Person) 
    records = new List (Of Person) 

    person.first = "Yogi" 
    person.last = "bear" 
    person.age = 35 

    records.Add(person) 
    records(0).first = "Papa" ' <<== Causes the error 
End Sub 
+9

每個.NET程序員都犯這個錯誤一次。結構是一個值類型,記錄(0)返回*副本*。更新副本的「第一個」成員不會完成任何操作。人需要成爲一個班級。 –

+0

從C++獲得遺留假設;)。謝謝你的提示。 –

+0

@Hans:是的,很容易忘記即使'records(0)'也會返回struct的一個副本...... – IAbstract

回答

13

由於其他意見小號當你引用記錄(0)時,你會得到一個結構體的副本,因爲它是一個值類型。你可以做什麼(如果你不能將其更改爲A類)是這樣的:

Dim p As Person = records(0) 
p.first = "Papa" 
records(0) = p 

雖然,我認爲它只是更容易使用一類。

+0

剛剛遇到這個問題,因爲我有一個字典,其值是一個結構而不是類。感謝您的簡單解決方案! – DontFretBrett

+0

這個問題是它複製整個結構而不是指向它的指針。這就是爲什麼你必須複製它。雙重打擊。很多的開銷。 – Brain2000

+0

@ Brain2000 - 同意,但使用值類型時,您沒有太多選擇。不僅因爲這個原因,「人」應該是一個階級,而且因爲可變結構不鼓勵。 –

4

實際上有兩個這裏要記住的重要概念。

之一是,如漢斯和Chris指出,Structure Person聲明一個值類型其中拷貝被方法調用之間傳遞。

儘管如此,仍然可以訪問(即獲取集合)值類型的成員。畢竟,作品:

Dim people(0) As Person 
people(0).first = "Yogi" 
people(0).last = "Bear" 
people(0).age = 35 

因此,要實現其他重要的一點是records(0)訪問List(Of Person)類的特殊Item財產,這是圍繞兩個方法調用(getter和含糖包裝二傳手)。它是不是的直接數組訪問;如果它是(即,如果records是一個數組),你的原始代碼實際上已經工作。

1

我有同樣的問題,我通過向改變屬性值的結構添加一個簡單的Sub來修復它。

Public Structure Person 

Dim first as String 
Dim last as String 
Dim age as Integer 

Public Sub ChangeFirst(value as String) 
    me.first = value 
End Sub 

End Structure