1

My assignment is to have a functionality which enables app user to sort RegisteredUser objects according to their filed/property values.

Assistant class inherits RegisteredUser. I would like somehow to be able to utilize lambdas and LINQ and to sort List<Assistants>. Is there a way to achieve this?

public abstract class RegisteredUser  
{
    protected int id;
    protected bool active;
    protected string name;

    //other fields and methods

    public static IComparer sortUsersByName(Order order)
    {
            return (IComparer)new nameFieldComparator(order);
    }

    private class nameFieldComparator : IComparer
    {
        private Order direction;

        public nameFieldComparator(Order direction)
        {
            this.direction = direction;
        }

        public int Compare(object x, object y)
        {
            if (x != null && y != null)
            {
                RegisteredUser user1 = (RegisteredUser)x;
                RegisteredUser user2 = (RegisteredUser)y;

                return (int)this.direction * String.Compare(user1.Name, user2.Name);

            }
            else throw new ArgumentNullException("Objects cannot be compared!");
        }
    }
}

My point of reference was How to use IComparer. I was trying different things, non worked.

Assistant a = new Assistant();
a.SetId(5);
a.Active = true;
a.Name = "asdasd"; 

Assistant f = new Assistant();
f.SetId(6);
f.Active = true;
f.Name = "asdf";


Assistant c = new Assistant();
c.Name = "a";
c.SetId(2);

List<RegisteredUser> l = new List<RegisteredUser>();
l.Add(a);
l.Add(f);
l.Add(c);
//list.Sort((x, y) => RegisteredUser.sortUsersByName()); of course, doesn't work...
List<Assistant> l = l.OrderBy() //tried bunch of ideas, but cannot get the syntax right

P.S. I am new to programming and c#

Stefan
  • 652
  • 5
  • 19
Wrapper
  • 794
  • 10
  • 25
  • 1
    Possible duplicate of [How to Sort a List by a property in the object](https://stackoverflow.com/questions/3309188/how-to-sort-a-listt-by-a-property-in-the-object) – Izzy Oct 24 '19 at 12:34
  • @Izzy Possible solution in link you gave aren't compatible with what I want to achieve. You see I have private IComparable, don't now how to call it (via public method ) in some linq expression or lambda... – Wrapper Oct 24 '19 at 12:44
  • 1
    @MiljanPuletic why use a private comparer at all, instead of a simple `OrderBy(x=>x.Name)`? In any case, [OrderBy](https://learn.microsoft.com/en-us/dotnet/api/system.linq.enumerable.orderby?view=netframework-4.8#System_Linq_Enumerable_OrderBy__2_System_Collections_Generic_IEnumerable___0__System_Func___0___1__System_Collections_Generic_IComparer___1__) has an overload that accepts an IComparer. In your case though that's just a string comparer for the names – Panagiotis Kanavos Oct 24 '19 at 13:00
  • Disregarding the question if using a custom `IComparer` where you can set the order yourself is the right thing to do (I agree it is not), IF you wanted to do it there are a few problems here. First of all this doesn't compile since `RegisteredUser` does not have a `Name` property (it has a `name` field but that is protected and not available in the `IComparer`). Also you're creating an `IComparer` but if you want to feed it to `OrderBy(Func, IComparer)` you need an `IComarer` which in this case would be an `IComparer` –  Oct 24 '19 at 13:36
  • @MiljanPuletic Does this answer your question? https://stackoverflow.com/questions/14336416/using-icomparer-for-sorting What about this answer in my possible dupe https://stackoverflow.com/a/3309397/1918179 ? – Izzy Oct 24 '19 at 14:18
  • If your question is entirely about the `private` nature of your `IComparer`, then my leading question would be: How else would you expect other pieces of code to be able to use anything `private` to your class? It violates OO! The sorting function must have access to the `IComparer` – Izzy Oct 24 '19 at 14:23
  • 1
    @Izzy You are right. I placed NameComparator IComparer in separate class, public of course and I'll just do: users.Sort(new NameComparator(Order.Ascending)). – Wrapper Oct 25 '19 at 09:47

3 Answers3

0

try this using Linq and lambdas:

 List<RegisteredUser> l = new List<RegisteredUser>();
 l.Add(a);
 l.Add(f);
 l.Add(c);

 var sortedList = l.OrderBy(x => x.Name).ToList();
g1b
  • 11
  • 2
  • But I want somehow to also be able to pass enum Order, to chose asc od desc order – Wrapper Oct 24 '19 at 12:58
  • @MiljanPuletic all of that is already available through LINQ using OrderBy andOrderByDescending. Passing `Order` has little meaning as the *comparison* results should remain the *same*, no matter what sort order you want. `1<3` even if you want to sort numbers in reverse order. What is the *actual* problem? Why create a private comparer like this? – Panagiotis Kanavos Oct 24 '19 at 13:04
  • @PanagiotisKanavos To be honest, I'm not really sure why. I wanted to have same/similar implementation of IComparer like in documentation. Can you show me how to get ascending and descending list of objects? – Wrapper Oct 24 '19 at 13:38
  • @MiljanPuletic g1b has a point that it is not necessary to implement IComparer. His example is quite plain. You can put it in a method and add a parameter saying it should sort ascending or descending (`OrderBy` vs `OrderByDescending`). Otherwise, take a look here: https://support.microsoft.com/nl-nl/help/320727/how-to-use-the-icomparable-and-icomparer-interfaces-in-visual-c . Maybe not use `IComparer`, but `IComparable`. – Stefan Oct 24 '19 at 14:05
0

This is a simple implementation of IComparable:

public abstract class RegisteredUser : IComparable
{
    public string Name { get; set; }

    // other properties


    public int CompareTo(object obj)
    {
        if (obj is RegisteredUser user)
            return this.Name.CompareTo(user.Name);

        return 1;
    }
}

public class Assistant : RegisteredUser
{

}

This is how to use it:

var users = new List<RegisteredUser>();
users.Add(new Assistant() { Name = "John" });
users.Add(new Assistant() { Name = "Joe" });

users.Sort();
Stefan
  • 652
  • 5
  • 19
0

The sorting method must have access to your implementation of IComparer, that means nameFieldComparator needs to be a public class in this case.

Izzy
  • 1,764
  • 1
  • 17
  • 31