Resolved Array Sort of Classes

MPIon

Well-known member
Joined
Jun 13, 2020
Messages
73
Location
England
Programming Experience
10+
I am new to this forum and not sure if this is the right place for this post, but I am having a problem with Array.Sort
I have a class
C#:
public class FileList
{
    public string path;
    public bool isFolder;
}
and an array set to this class :-
C#:
public static FileList[] fileList = new FileList[1000];

for (int i = 0; i < 1000; i++)
    fileList = new FileList();

I now want to sort this class and following examples on the internet I have used :-
C#:
Array.Sort(fileList, (x, y) => string.Compare(x.path, y.path));
This works, but I want to restrict to sorting only some of the elements, so tried
C#:
Array.Sort(fileList, 0, 10, (x, y) => string.Compare(x.path, y.path));
This gives two compilation errors:
Argument 2, cannot convert from int to system array
and
Cannot convert lambda expression to type int because it is not a delegate type.
Can't comprehend what this means or find any help on the internet that might explain what is going wrong here. I think I may need to write some sort
of ICompare routine, but none of the examples I found had a reference to one element of the Class.

I'm sure there must be a simple solution, without reinventing the wheel.
 
Last edited by a moderator:
If the first one worked, the second one should have also worked, but I'm reading this on a small screen, and scrolling up and down so I maybe missing something.

Out of curiosity, it looks like you want to sort only the first 10 items. Is your intent to keep the other 990 items intact? Or you don't care about the rest?
 
If the first one worked, the second one should have also worked, but I'm reading this on a small screen, and scrolling up and down so I maybe missing something.

Out of curiosity, it looks like you want to sort only the first 10 items. Is your intent to keep the other 990 items intact? Or you don't care about the rest?
Thanks for the reply. Yes I also thought the second one should have worked as I believe this is an overload of the Array.Sort method.
I only wanted to sort the populated entries in the array - 10 was just an example. What was happening was all empty entries were being sorted first in the list, but I'm not interested in them.
I am now looking at using a List and only adding items to it when needed. Not sure how efficient this is though. Maybe more efficient than using a dynamically sized array.
 
The first code that works is using this overload. The second parameter is type Comparison<T>. That is the ONLY overload with a parameter of that type so of course calling the method with any other combination of arguments and a Comparison<T> won't work. The overload you're trying to call would require an IComparer<T>, which means an instance of a class that has a method that does the same comparison, e.g.
C#:
public class FileListPathComparer : IComparer<FileList>
{
    public int Compare(FileList x, FileList y)
    {
        return string.Compare(x.path, y.path);
    }
}
and:
C#:
Array.Sort(fileList, 0, 10, new FileListPathComparer());
 
Not sure how efficient this is though. Maybe more efficient than using a dynamically sized array.
It is. In fact, a List<T> uses an array internally and will dynamically resize it as required but using an algorithm specifically intended to be fairly efficient. The Capacity is the size of the internal array and that gets doubled each time more space is required. That way, fewer resizes are needed for bigger lists. If you have a fair idea of what the final size will be then you can specify the capacity when you create the List<T> and then no resizing will be required. The list object still appears to be only as big as the items you've added from the outside. All the empty array elements are automatically managed by the class.
 
Or use Comparer<T>.Create(). To get something like:
C#:
Array.Sort(fileList, 0, 10, Comparer<FileList>.Create((x, y) => string.Compare(x.path, y.path)));

And yes, definitely prefer to use a List<T> rather than an array.
 
Or use Comparer<T>.Create(). To get something like:
C#:
Array.Sort(fileList, 0, 10, Comparer<FileList>.Create((x, y) => string.Compare(x.path, y.path)));

And yes, definitely prefer to use a List<T> rather than an array.
Wasn't aware of that class. On the rare occasions I've needed that functionality I've always implemented the interfaces directly. That's not too onerous so it's not a big deal but I still wish I'd been aware.
 
The first code that works is using this overload. The second parameter is type Comparison<T>. That is the ONLY overload with a parameter of that type so of course calling the method with any other combination of arguments and a Comparison<T> won't work. The overload you're trying to call would require an IComparer<T>, which means an instance of a class that has a method that does the same comparison, e.g.
C#:
public class FileListPathComparer : IComparer<FileList>
{
    public int Compare(FileList x, FileList y)
    {
        return string.Compare(x.path, y.path);
    }
}
and:
C#:
Array.Sort(fileList, 0, 10, new FileListPathComparer());
Thanks J,
That seems to solve it. I will use a List rather than an array though. Could do either as the array is very small and don't need performance with this.
It's good to try out new things though. Much to learn there is.
 
Or use Comparer<T>.Create(). To get something like:
C#:
Array.Sort(fileList, 0, 10, Comparer<FileList>.Create((x, y) => string.Compare(x.path, y.path)));

And yes, definitely prefer to use a List<T> rather than an array.
Yes, I've now got the code up and running using a List and don't need to restrict the sort to 10 or whatever is occupied, as the List only contains populated items.
Thanks, I'll mark this thread Solved, if I can figure out how to do that.
 
Thanks J,
That seems to solve it. I will use a List rather than an array though. Could do either as the array is very small and don't need performance with this.
It's good to try out new things though. Much to learn there is.
Some people recommend never using an array because a List<T> is more flexible but that always seems silly to me. You should always use the most appropriate tool for the job at hand. If you need a list of items that will never change then an array is the best tool because it does that with the least overhead. If the list will change then a List<T> is better because it allows you to do that efficiently and with the most readable and maintainable code. There is almost always a grey area too. If, for instance, you had a list that would change once but you didn't know by how much, it might be prudent to use an array and resize it yourself. That way, you'd always just use as much space as you needed. If you used a List<T>, you might end up resizing the internal array anyway and then using a much larger array than is actually required.
 
Last edited:
Back
Top Bottom