过滤通用类型列表?

时间:2016-09-08 23:06:26

标签: c# generics

我有一个返回Generic Type列表的方法

List<T> GetResultList<T>()

T是上课。对于每个班级,都有一个会员日期。现在,我想按日期过滤GetResultList中的T列表。有可能吗?

或者,我必须在每个班级都这样做?

更重要的是,在不同的类中,成员应该在过滤器中使用是不同的,即对于class1,我想过滤Date,对于class2,我想过滤Date2。这可以在GetResultList而不是每个类中完成吗?

由于

4 个答案:

答案 0 :(得分:1)

过滤已知字段的选项

(a)最佳选择:创建描述合同的接口(例如,存在Date属性)并将您的泛型类型约束到该接口。 此选项具有静态类型的好处:使用未实现接口的T是编译时错误。

interface IDated 
{
  DateTime Date { get; } 
}

List<T> GetResultList<T>() where T: IDated
{
  T x;
  if (x.Date == DateTime.Today); // You can access T.Date
}

(b)所有其他解决方案都是运行时动态访问。当然,从dynamic开始,或使用反射按名称访问成员。它们都有缺点,即在编译时没有验证其正确性(即在运行时使用TDate失败)和性能开销。

过滤“未知”字段的选项

  

成员应该在过滤器中使用不同

(a)用一致的界面统一它们并使用上面的选项(a)。

(b)将字段名称传递给动态或基于反射的代码。

(c)传递一个谓词,就像LINQ Where方法一样。类似的东西:

List<T> GetResultList<T>(Func<T, bool> predicate)
{
  T x;
  if (predicate(x)) /*...*/;
}

// Usage:
GetResultList<MyObject>(x => x.Date == DateTime.Today);

编辑:如果您不想在来电者网站编码条件,则可以传递值提取器(投影/类似Select):

List<T> GetResultList<T>(Func<T, DateTime> getDate)
{
  T x;
  if (getDate(x) == DateTime.Today) /*...*/;
}

// Usage:
GetResultList<MyObject>(x => x.Date);

答案 1 :(得分:0)

如果你知道T可以表示的任何东西都有一个名为Date的属性,那么你可以实现和接口IHasDate(或其他)......然后如果你在你的泛型参数中包含一个条件,那么传入的任何东西都会有T物业可用。

未经测试的代码......

public interface IHasDate
{
    DateTime Date { get; }
}

public List<T> GetResultsList<T>()
    where T : IHasDate
{
    var list = new List<T>();
    //Fill list
    list.Sort((t1, t2) => t1.Date.CompareTo(t2.Date));
    Return t;
}

答案 2 :(得分:0)

传递代表:

GetResultList(x => x.Date2);

并更新您的GetResultList函数以使用该代理:

List<T> GetResultList<T>(Func<T, Date> dateGetter)
{
    return someList.OrderBy(x => dateGetter(x)).ToList();
}

答案 3 :(得分:0)

<强> 1) 既然您谈到List<T>列表中的所有对象都已经有了接口 - 那么经典解决方案就是在类中实现特殊方法(这里T是{{1} }}):

IClassWithDate

2)但是既然你不想在课程中实现任何逻辑,你可以使用另一种方法 - 使用dynamis

public interface IClassWithDate
{
    DateTime DateForFiltering();
}

internal class classDerrivedFromInterface1 : IClassWithDate
{
    public DateTime Date;
    public int AnotherField;

    public DateTime DateForFiltering()
    {
        return Date;
    }
}

internal class classDerivvedFromInterface2 : IClassWithDate
{
    public DateTime Date2;
    public int AnotherField;

    public DateTime DateForFiltering()
    {
        return Date2;
    }
}
public List<IClassWithDate> GetResultList<IClassWithDate>()
{               
    var listOfIClassesWithDate = new List<IClassWithDate> { new classDerrivedFromInterface1 { Date = DateTime.MinValue, AnotherField = 2 }, new classDerivvedFromInterface2 { Date2 = DateTime.MinValue, AnotherField = 2 } };
    return listOfSimpleClasses.Where(x => x.DateForFiltering() == DateTime.MinValue).ToList();
}

3)与第二次相同,但没有动态(这就是为什么这种方式比2更好)。您应该使用类型转换和对象

class simpleClass1
{
    public DateTime Date;
    public int AnotherField;
}

class simpleClass2
{
    public DateTime Date2;
    public int AnotherField;
}

public List<dynamic> GetResultList()
{               
        var listOfSimpleClasses = new List<dynamic> {new simpleClass1 {Date = DateTime.MinValue, AnotherField = 2}, new simpleClass2 {Date2 = DateTime.MinValue, AnotherField = 2}};
        return listOfSimpleClasses.Where(x =>
        {
            if (x is simpleClass2)
                return x.Date2 == DateTime.MinValue;
            if (x is simpleClass1)
                return x.Date == DateTime.MinValue;
            return false;
        }).ToList();