2013-11-01 75 views
3

我想排序一個實現IEnumerable的VB類。 我不想要一個新的對象/ linq。 它必須保持原始對象,但排序。 這是一個示例類。VB.NET排序IEnumerable類

Public Class Person 
    Public Sub New(ByVal fName As String, ByVal lName As String) 
     Me.firstName = fName 
     Me.lastName = lName 
    End Sub 

    Public firstName As String 
    Public lastName As String 
End Class 

Public Class People 
    Implements IEnumerable(Of Person) 

    Private _people() As Person 

    Public Sub New(ByVal pArray() As Person) 
     _people = New Person(pArray.Length - 1) {} 

     Dim i As Integer 
     For i = 0 To pArray.Length - 1 
      _people(i) = pArray(i) 
     Next i 
    End Sub 

    Public Function GetEnumerator() As IEnumerator(Of Person) _ 
      Implements IEnumerable(Of Person).GetEnumerator 
     Return DirectCast(_people, IEnumerable(Of Person)).GetEnumerator 
    End Function 

    Private Function System_Collections_GetEnumerator() As IEnumerator _ 
      Implements IEnumerable.GetEnumerator 
     Return Me.GetEnumerator 
    End Function 
End Class 

我知道我可以使用LINQ,但然後我得到一個新的對象不是原來的排序。 有太多的地方使用全球「peopleList」對象,所以我需要對「peopleList」進行排序,而不是一個新的「人物」排序列表。

Dim peopleList As New People({ _ 
    New Person("John", "Smith"), _ 
    New Person("Jim", "Johnson"), _ 
    New Person("Sue", "Rabon")}) 
Dim newPeopleList = From person In peopleList Order By person.firstName Select person 
'OR 
Dim newPeopleList = DirectCast(peopleList, IEnumerable(Of Person)).ToList() 
newPeopleList.Sort(Function(p1, p2) p1.firstName.CompareTo(p2.firstName)) 

我需要更類似於下面的內容。

Dim peopleList As New People({ _ 
    New Person("John", "Smith"), _ 
    New Person("Jim", "Johnson"), _ 
    New Person("Sue", "Rabon")}) 
peopleList = peopleList.Sort(Function(p) p.firstName) 

我知道IEnumerable沒有Sort方法。我只是把它作爲一個例子。 我確實有修改「People」類的選項,但最終它仍然必須實現IEnumerable,因爲我不想打破當前的調用者。 此外,當前的調用者必須能夠看到排序的「peopleList」。

回答

5

您可以爲正在創建的People列表中的Person對象進行排序:

Public Sub New(ByVal pArray() As Person) 
    _people = New Person(pArray.Length - 1) {} 

    Dim i As Integer = 0 
    For 
    For Each person In pArray.OrderBy(Function(p) p.firstName) 
     _people(i) = person 
     i = i + 1 
    Next i 
End Sub 

或者,您也可以提供自己的方法,它已被創建後內部數組排序。像這樣的東西應該工作:

Public Class People 
    Public Sub Sort(Of T As IComparable)(KeySelector As Func(Of Person, T)) 
     Array.Sort(_people, Function(x, y) KeySelector(x).CompareTo(KeySelector(y))) 
    End Sub 
End Class 

而且你可以調用像這樣的:

peopleList.Sort(Function(p) p.firstName) 
+0

這是一個選項,但在查詢對象之前,其他一些方法會填充對象。因此,某種「Sort」方法/功能會更好。像這樣的東西http://danielsaidi.wordpress.com/2009/08/27/sort-ienumerable-and-list-with-property-name/,但在VB中。 – goroth

+0

@goroth查看我的更新答案替代 –

+0

我喜歡更新的答案,但它不能在我的機器上使用.NET 3.5進行編譯...行Func(Person,T) - 「數組邊界不能出現在類型說明符中「 – goroth

1

你可以只排序的基本數組和使用自定義的IComparer適合:

http://msdn.microsoft.com/en-us/library/bzw8611x.aspx

類似於:

public class PersonComparer: IComparer<Person> 
{ 
    public int Compare(Person x, Person y) 
    {    
     return x.FirstName.CompareTo(y.FirstName); 
    } 
} 

然後在你的人物等級:

public sub Sort() 

    PersonComparer pc = new PersonComparer() 

    Array.Sort(_people, pc) 

end sub 
+0

我已經走了這條路,但從來沒有想過如何通過除名字以外的其他屬性進行排序。如LastName。 – goroth

+0

那麼,如果你能使它適用於'FirstName',那表明你在正確的道路上。也許你應該問一個單獨的問題,你可以如何讓比較器使用多個字段(但是確實如此:在你提出這個問題之前,試着在一張紙上算出邏輯,這並不複雜!)。 –

+0

p.s.w.g的答案似乎是實現您所尋找的一種好方法。 – Paddy

1

您可以只需添加一個Sort方法:

Public Sub Sort() 
    _people = _people.OrderBy(Function(p) p.firstname).ToArray() 
End Sub 

Public Sub Sort(Of TKey)(keySelector As Func(Of Person, TKey)) 
    _people = _people.OrderBy(keySelector).ToArray() 
End Sub 

或排序,當您返回枚舉:

Public Function GetEnumerator() As IEnumerator(Of Person) _ 
     Implements IEnumerable(Of Person).GetEnumerator 
    Return _people.OrderBy(Function(p) p.firstname).GetEnumerator() 
End Function