0

Given this code:

class Pet
{
    public string Name { get; set; }
    public int Age { get; set; }
}

public static void OrderByEx1()
{
    Pet[] pets = { new Pet { Name="Barley", Age=8 },
                   new Pet { Name="Boots", Age=4 },
                   new Pet { Name="Whiskers", Age=1 } };

    IEnumerable<Pet> query = pets.OrderBy(pet => pet.Age == 8 ? 0 : 1);

    foreach (Pet pet in query)
    {
        Console.WriteLine("{0} - {1}", pet.Name, pet.Age);
    }
}

Is it possible to extract pet => pet.Age == 8 ? 0 : 1 into its own method and do some conditonal statements based on pet.Age without using ternary operations?

To add to this, I have tried doing something like this:

IEnumerable<Pet> query = pets.OrderBy(pet => NewMethod(pet));

And define the method as such:

private static Expression<Func<Pet, int>> NewMethod(Pet pet)
{
    if(pet.Age == 8)
        return 0;
    else
        return 1;
}

But that does not seem to work as intended.

But doing this:

IEnumerable<Pet> query = pets.OrderBy(NewMethod);

And this, works fine:

private static Expression<Func<Pet, int>> NewMethod(Pet pet)
{
    return pet => pet.Age == 8 ? 0 : 1;
}
user2831306
  • 33
  • 1
  • 6
  • Are you asking "how to use 'extract local function' refactoring in VS when you select lambda expression inside `OrderBy`"? – Alexei Levenkov Oct 10 '22 at 18:40
  • The answer is yes. You need to learn about [Delegates](https://learn.microsoft.com/en-US/dotnet/csharp/programming-guide/delegates/#delegates-overview) and [Lambda Expressions](https://learn.microsoft.com/en-US/dotnet/csharp/language-reference/operators/lambda-expressions#expression-lambda). – Aluan Haddad Oct 11 '22 at 01:24
  • Could you please show how you would do that @AluanHaddad? – user2831306 Oct 12 '22 at 12:34

1 Answers1

1

You can create a class which implements IComparer<T> where T is your class type Pet and then pass an instance of this into OrderBy:

public class MyPetAgeComparer : IComparer<Pet>
{
     public int Compare(Pet a, Pet b)
     {
         //Add your comparison logic here
     }
}

In code usage:

public static void OrderByEx1()
{
     Pet[] pets = { new Pet { Name="Barley", Age=8 },
               new Pet { Name="Boots", Age=4 },
               new Pet { Name="Whiskers", Age=1 } };
     //Here you would pass in an instance of your custom
     //comparer class as the second parameter of OrderBy
     IEnumerable<Pet> query = pets.OrderBy(pet => pet, new MyPetAgeComparer());

     foreach (Pet pet in query)
     {
         Console.WriteLine("{0} - {1}", pet.Name, pet.Age);
     }
}

More information on OrderBy - system.linq.enumerable.orderby

Ryan Wilson
  • 10,223
  • 2
  • 21
  • 40
  • Yes this is an option, but it completely sidesteps the question. Additionally, it is awkward, not idiomatic, and create a bunch of unnecessary cruft. – Aluan Haddad Oct 11 '22 at 01:17
  • @AluanHaddad Complete hogwash. It's an overload of the method for a reason. – Ryan Wilson Oct 11 '22 at 01:48
  • It's there for a reason. This is not that reason. Also, it's clear that the OP doesn't understand delegates and passing methods to other methods, which is a fundamental concept in C#. Answer the question he asked. – Aluan Haddad Oct 11 '22 at 02:04
  • @AluanHaddad I answered the question. You're the one complaining about it. If you don't like it, provide one of your own. Your comment about this not being the reason is shoddy and has no evidential reason. – Ryan Wilson Oct 11 '22 at 02:12
  • @AluanHaddad "Is it possible to extract pet => pet.Age == 8 ? 0 : 1 into its own method and do `some conditonal statements` based on pet.Age without using ternary operations. Implies multiple conditions which would be easily readable in a custom comparer, not to mention it follows the S in Solid design – Ryan Wilson Oct 11 '22 at 02:16
  • The comparer class that you wrote contains a method. You don't need the class you just need the method. This has nothing to do with the single responsibility principle. – Aluan Haddad Oct 11 '22 at 02:17
  • @AluanHaddad The class contains the method hence the interface implementation and yes it does have something to do wth single responsibility. [single-rrsponsibility](https://www.c-sharpcorner.com/article/solid-single-responsibility-principle-with-c-sharp/) – Ryan Wilson Oct 11 '22 at 02:22
  • I don't see how nested methods violate SRP. What about the principle of least privilege, in order to follow that you'd have to declare the comparer as a nested class anyway. – Aluan Haddad Oct 11 '22 at 02:28
  • @AluanHaddad Im talking about how the custom comparer class fulfills the Solid design, not saying your proposal violates it. Since apparently I have to defend a valid answer – Ryan Wilson Oct 11 '22 at 02:29
  • We're just talking past each other now. – Aluan Haddad Oct 11 '22 at 02:32