简体   繁体   English

从List中查找最大值<T>

[英]Finding max value from within List<T>

I have a number of objects defined, each has a property named "CreateDate". 我定义了许多对象,每个对象都有一个名为“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();
}

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 . 如果那不是一个选项(可能是因为你不能修改类让它实现接口或集合来包装底层类型)你可以使用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);
}

You can use Reflection to get the property name by string value like this: 您可以使用Reflection通过字符串值获取属性名称,如下所示:

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. 它现在应该可以正常工作,并且它将按照您希望的方式保持通用。

You can encapsulate CreateDate property in a base class (eg BaseClass) and do smth like this 您可以将CreateDate属性封装在基类(例如BaseClass)中并像这样执行smth

private static DateTime GetLastDate<T>(List<T> data) where T : BaseClass
{
     ...
}

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();

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM