Click here to Skip to main content
15,867,594 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I have a program that currently distributes chocolates to x people in a list, and I have a general method that handles the sorting and several methods that orders the list by age, first name etc. depending on how you'd like to distribute the chocolates. My program is working, but is there a way to create ONE method that can take a parameter that handles the sorting? For examle, this is one of the methods that distributes chocolates by age:

C#
public void DistributeChocolatesByAge(int choc)
{
        People = People.OrderBy(x => x.Age).ToList();
        ChocolatesDistributed(choc);
}

ChocolatesDistributed is my "general" distribution method. Is there a way to make my general method take a parameter that handles distribution of chocolates by age (or firstName/lastName) as the method above is doing for me right now? Right now I just have several methods almost doing the same thing.

What I have tried:

I have tried to pass OrderBy as parameter but that does obviously not work.
Posted
Updated 29-Nov-21 2:46am
Comments
Richard MacCutchan 28-Nov-21 11:29am    
You could use an enum type as the input parameter. You would then need a switch block in your method to decide how to sort the list.
George Swan 28-Nov-21 17:33pm    
Try a method like this
public int DistributeChocolate(int chocolateCount,IEnumerable<person>selectedPeople )
And call it something like this
int chocsLeft=DistributeChocolate(chocolateCount,people.Where(p => p.Age > 20));

You could do it this way:

C#"
public void DistributeChocolatesByAge(int choc)
{
    ChocolatesDistributed(choc, People.OrderBy(x => x.Age).ToList());
}


However, I would probably move the sort operation into the ChocolatesDistributed method so that it happens every time you call that method, thus guaranteeing that the people collection is always sorted when displayed. That's just me though.

If you only want to show a people of a given age, there's no point in sorting the collection when you can simply do this:

C#
ChocolatesDistributed(People.Where(x=>x.Age==choc).ToList());


I'm assuming choc is a poorly named parameter that indicates the desired age.
 
Share this answer
 
v2
Comments
evedvvv 28-Nov-21 11:58am    
My program, with all of my methods that I have at the moment, is working fine. The problem is that I have one method that distributes chocolates and three other methods that ORDER my list, and then I call my distribution method in them. So basically I have several methods almost doing the exact same thing:

public void DistributeChocolatesByAge(int chocolates)
{
People = People.OrderBy(x => x.Age).ToList();
ChocolatesToDistribute(chocolates);
}

public void DistributeChocolatesByFirstName(int chocolates)
{
People = People.OrderBy(x => x.FirstName).ToList();
ChocolatesToDistribute(chocolates);
}

public void DistributeChocolatesByLastName(int chocolates)
{
People = People.OrderBy(x => x.LastName).ToList();
ChocolatesToDistribute(chocolates);
}

My professor said that my code looks right but that it would be nicer to just have +1 overload on my general distribution method, that will take a parameter that handles the sorting/order of my list:

public void ChocolatesToDistribute(int chocolates) //instead of chocolates
{
int chocolatesAmount = chocolates;
for(int i = 0; i < chocolates; i++)
{
foreach (Person person in People)
{
if(chocolatesAmount > 0)
person.Chocolates++;
chocolatesAmount--;
}
}
}
#realJSOP 28-Nov-21 15:22pm    
You actually don’t need any overloads, or any of the the DistributeChocolatesBy… methods. Have you learned about enumerators and default parameters yet?
evedvvv 28-Nov-21 17:58pm    
No, but I've been reading about IEnumerable and it seems like it is what I'm looking for. But since we haven't learned it I'm not sure if there is a more "simple/beginner"- approach to do this.
Pass in the sort as a lambda:

public void DistributeChocolates<T>(int choc, Func<T> sorter)
{
        People = People.OrderBy(sorter).ToList();
        ChocolatesDistributed(choc);
}
Call with:
DistributeChocolates(5, x => x.Age);
 
Share this answer
 
Comments
#realJSOP 28-Nov-21 18:01pm    
Oooooh, I like that. But I think that’s more than he’s been taught. :)
Marc Clifton 29-Nov-21 8:48am    
My example was quite fubar'd, though the concept was ok. I posted a full working example.
BillWoodruff 29-Nov-21 1:32am    
Interesting: I am evaluating why the T here is not declared IEnumerable, and why People is not passed, as a param, to DistributeChocolates ... makes me "nervous" ... I'll get over it :)
Marc Clifton 29-Nov-21 8:22am    
Agreed - there is much wrong with the original code example that I didn't bother to address. And my example was wrong. I posted a correct full example.
evedvvv 29-Nov-21 3:16am    
Nice and simple way to do it. I have tried it but I get an error; The type arguments for method 'method' cannot be inferred from the usage. Try specifying the type arguments explicitly.
Here's the full example. Not really sure what you're trying to do with numChocolates, but the rest of it illustrates passing in the order by expression. Note how it handles any type, such as int, string, double. It was interesting to figure out the nuance of this.

using System;
using System.Collections.Generic;
using System.Linq;

namespace CPDemo
{
    class Person
    {
        public int Age { get; set; }
        public string LastName { get; set; }
        public string FirstName { get; set; }
        public double Distance { get; set; }

        public override string ToString()
        {
            return $"{LastName}, {FirstName}, {Age}, {Distance}";
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            var people = new List<Person>()
            {
                new Person() {Age = 50, LastName = "Shmo", FirstName = "Joe", Distance = 10 },
                new Person() {Age = 40, LastName = "Doe", FirstName = "Jane", Distance = 5 },
                new Person() {Age = 30, LastName = "Willard", FirstName = "Willy", Distance = 1 }
            };

            Console.WriteLine("By age:");
            DistributeChocolates(people, 5, x => x.Age);
            Console.WriteLine();
            Console.WriteLine("By last name:");
            DistributeChocolates(people, 5, x => x.LastName);
            Console.WriteLine();
            Console.WriteLine("By distance:");
            DistributeChocolates(people, 5, x => x.Distance);
        }

        static void DistributeChocolates<T>(IEnumerable<Person> people, int numChocolates, Func<Person, T> sorter)
        {
            var toPeople = people.OrderBy(sorter);
            Ship(toPeople, numChocolates);
        }

        static void Ship(IEnumerable<Person> people, int numChocolates)
        {
            foreach (Person person in people)
            {
                Console.WriteLine(person.ToString());
            }
        }
    }
}


This is the output:

By age:
Willard, Willy, 30, 1
Doe, Jane, 40, 5
Shmo, Joe, 50, 10

By last name:
Doe, Jane, 40, 5
Shmo, Joe, 50, 10
Willard, Willy, 30, 1

By distance:
Willard, Willy, 30, 1
Doe, Jane, 40, 5
Shmo, Joe, 50, 10
 
Share this answer
 

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900