2013-11-01 39 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