Search code examples
c#asp.net-core

get highest count of Enumerable objects in class


Here I have the following to act as an example

public class Items
    {
        public ICollection<ClassName1> Items1 { get; set; }
        public ICollection<ClassName2> Items2 { get; set; }
        public ICollection<ClassName3> Items3 { get; set; }
    }

class Items contain ICollections of strongly typed classes ClassName1, ClassName2, ClassName3

    var items = new Items()
    {
        Items1 = GetItems1(),
        Items2 = GetItems2(),
        Items3 = GetItems3()
    }

What I want to do:

// Get the count of the highest count in items

What is a good method to get the highest count from items?

How could Max() be attained without writing each object individually as listed in the this example?

{ items.Items1.Count, items.Items2.Count, items.Items3.Count }.Max() 

So instead

{some kind of iterative process to get .Count() of properties in items}.Max()

Solution

  • What it sounds like is that you have an object of some class (Items), and you are interested in finding the .Count of all the public properties which implement IEnumerable.

    Redefining your example class:

    class Items
    {
        public ICollection<string> A { get; set; }
        public ICollection<int> B { get; set; }
        public ICollection<char> C { get; set; }
        public double D { get; set; } // property to ignore
    }
    

    And this is how you make the object, somewhere else in your code:

    var items = new Items
    {
        A = ["one", "two", "three", "four"],
        B = [1,2,3,4,5],
        C = ['a', 'b']
    };
    

    Now the task is, without using the property name at compile time, get the values of each of the properties of the items object which implement IEnumerable to find the .Count, and find the .Max() from there.

    If you're only after the number that is the highest, and not what property that highest count belongs to, do something like this:

    var highestPropertyCollectionCount = typeof(Items)
        .GetProperties()
        .Where(prop => prop.PropertyType.IsAssignableTo(typeof(IEnumerable)))
        .Select(prop => (IEnumerable)prop.GetValue(items))
        .Max(collection => collection.Cast<object>().Count());
    
    1. typeof(Items) can be replaced by items.GetType() if you don't know the type at compile type
    2. You need to use IEnumerable rather than ICollection. I'm not 100% sure the reason though.

    In this example case, highestPropertyCollectionCount will be "5" (the count of the items in B).

    If you're only interested in which property has the most elements, and not what the count of the collection is, you can do an alteration after the Where

    var propertyWithMostElements = typeof(Items)
        .GetProperties()
        .Where(prop => prop.PropertyType.IsAssignableTo(typeof(IEnumerable)))
        .OrderByDescending(prop => ((IEnumerable)prop.GetValue(items)).Cast<object>().Count())
        .First();
    

    propertyWithMostElements would be the PropertyInfo for B.