views:

73

answers:

2

I know it must have been asked more than twice, but I could not find any applicable question to answer the matter.

I have a collection which I wish to retrieve an array from in .NET 2.0. In other words, I want to convert a collection into an array. So far I have the following:

Public Class Set(Of T)
    Implements IEnumerable(Of T)
    Implements ICollection(Of T)
    Implements IEqualityComparer(Of T)

    Private _set as Dictionary(Of T, Object)

    // Implementing the interfaces here...

    Public Function ToArray() As Array
        Dim arr As Array = Array.CreateInstance(GetType(T), Me.Count)
        Me.CopyTo(arr, 0)
        Return arr
    End Function
End Class

And then, when I'm calling it, I simply have to:

Dim propertiesToLoad As CustomSet(Of String) = New CustomSet(Of String)()
// Initializing my CustomSet here...

Dim searcher As DirectorySearcher = New DirectorySearcher()
Dim entry As DirectoryEntry = New DirectoryEntry("LDAP://" & Environment.UserDomain)

searcher.SearchRoot = entry
searcher.SearchScope = SearchScope.Subtree
searcher.Filter = someFilter
searcher.PropertiesToLoad.AddRange(propertiesToLoad.ToArray())

// Launching search here...

Is there a more effective way to do it in .NET 2.0?

EDIT #1

Implementations of Count and CopyTo in my CustomSet(Of T):

Public ReadOnly Property Count As Integer Implements ICollection(Of T).Count
    Get
        Return _set.Keys.Count
    End Get
End Property

Public Sub CopyTo(ByVal array As T, ByVal arrayIndex As Integer) Implements ICollection(Of T).CopyTo
    _set.Keys.CopyTo(array, arrayIndex)
End Sub
+1  A: 

You should change your AddRange method to take an IEnumerable<T> or an ICollection<T> (if you need Count).
This way, you won't need to call ToArray at all, saving a memory allocation.

Your implementation looks fine.
However, note that Dictionary<TKey, TValue> is unordered.

SLaks
DirectorySearcher is a .NET class, part of the System.DirectoryServices namespace. PropertiesToLoad is a StringCollection, so it can't be changed
Panagiotis Kanavos
@SLaks: Agreed! Thanks for the tip. Thus I can't change the `AddRange()` method as it is part of .NET 2.0 as per the `System.DirectoryServices.DirectorySearcher.PropertiesToLoad.AddRange()`. Despite, the `PropertiesToLoad` property is a `StringValueCollection`. I guess there could be some way to assign my collection directly to it, but it doesn't seem to work as-is. What are, according to your thoughts, the changes I could make to make it possible? Should I implement an additional interface in my `CustomSet(Of T)` class so that it is compatible with the `StringValueCollection` class?
Will Marcouiller
I missed that part.
SLaks
+1  A: 

You don't need to use CreateInstance to create the array, you know the type, and you can even return it as an array of the specific type:

Public Function ToArray() As T()
  Dim arr(Me.Count) As T
  Me.CopyTo(arr, 0)
  Return arr
End Function

How efficient this is, of course relies on how efficient your implementations of ICollection(Of T).Count and ICollection(Of T).CopyTo are.

Guffa
@Guffa: That, I didn't know how to do in VB.NET. Thanks for this suggestion! As for the implementations of Count and CopyTo, please see the code I'm going to provide in my EDIT #1. Thanks! =)
Will Marcouiller
@Will: That looks efficient enough. It might be possible to improve on it slightly if you loop through the items in the dictionary directly instead of using the `Keys` collection, but that is hardly worth the added complexity.
Guffa
@Guffa: Thanks for your comment and traces of improvement, even though these are hardly worth it due to complexity. I appreciate these hints. =)
Will Marcouiller