Finding max value from within List<T>
Asked Answered
T

4

6

I have a number of objects defined, each has a property named "CreateDate".

Is it possible to write a single, generic method to select the highest date from an object that I specify?

I was attempting to use a generic approach to this, but the compiler doesn't like it when I try to specify a property name.

I was trying to achieve something along these lines...

private static DateTime GetLastDate<T>(List<T> data)
{
    // Unfortunately, this is not allowed...
    return
        (from d in data
        orderby d.CreateDate
        select d.CreateDate).FirstOrDefault();
}
Twicetold answered 5/11, 2012 at 20:57 Comment(0)
H
11

The best method would be to create an interface with the specific functionality and have all of the classes implement that interface:

public interface ICreated
{
  public DateTime CreateDate {get;}
}

Then you can ensure that all of the items accepted implement that interface:

private static DateTime GetLastDate<T>(IEnumerable<T> input) where T : ICreated
{
    return input.Max(d=>d.CreateDate);
}

If that's really not an option (possibly because you can't modify the class to have it implement the interface or the collection to wrap the underlying type) you could use dynamic. I would highly discourage that you do this as it's really not good design, it will be much slower, and it's rather susceptible to breaking, but it could work:

private static DateTime GetLastDate(IEnumerable<dynamic> input)
{
    return input.Max(d=>d.CreateDate);
}
Hodgkinson answered 5/11, 2012 at 21:1 Comment(0)
C
2

You can use Reflection to get the property name by string value like this:

You'll need this method to get the actual property by string value, if you're planning on working with allot of generic stuff you might be interested in putting this someplace you can reuse it.

// Add ' using System.Reflection; ' on top
public static object GetPropertyValue(object o, string propertyName)
        {
            Type type = o.GetType();
            PropertyInfo info = type.GetProperty(propertyName);
            object value = info.GetValue(o, null);
            return value;
        }

With that method you can do this instead of the code that isn't working for you:

private static DateTime GetLastDate<T>(List<T> data)
    {
        object value = (from d in data
             orderby GetPropertyValue(d, "CreateDate")
             select GetPropertyValue(d, "CreateDate")).FirstOrDefault();

        return DateTime.Parse(value.ToString());
    }

It should work perfectly fine now, And it'll stay generic just the way you want it to be.

Cheder answered 5/11, 2012 at 23:31 Comment(0)
M
1

You can encapsulate CreateDate property in a base class (e.g. BaseClass) and do smth like this

private static DateTime GetLastDate<T>(List<T> data) where T : BaseClass
{
     ...
}
Melpomene answered 5/11, 2012 at 21:2 Comment(0)
F
1

I simply did this and created a generic method in my extension class

 public static object GetPropertyValue(this object o, string propertyName)
    {
        Type type = o.GetType();

        try
        {
            PropertyInfo info = (from x in  type.GetProperties() where x.Name.ToLower() == propertyName.ToLower() select x).First();
            object value = info.GetValue(o, null);
            return value;
        }
        catch (Exception ex)
        {
            return default(object);
        }
    }

    public static T GetFieldValue<T>(this object o, string propertyName) where T : struct, IComparable, IFormattable, IConvertible, IComparable<T>, IEquatable<T>
    {
        try
        {
            var val = GetPropertyValue(o, propertyName);
            return (T)val;
        }
        catch (Exception ex)
        {
            return default(T);
        }
    }

And this is how I used it...

var max_cust_id = (string)(from m in final_list.Skip((int)offset)
                                   orderby m.GetPropertyValue(identityField)
                                   select m.GetPropertyValue(identityField)).Max();
Fadge answered 8/2, 2017 at 7:38 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.