【问题标题】:Can I use Strongly type parameters based on properties from Object我可以使用基于对象属性的强类型参数吗
【发布时间】:2015-11-26 21:10:11
【问题描述】:

我有一个对象列表。 我有一个与列表类型相同的项目。

我想创建一个通用扩展方法(称为 Find),以根据单个 obj 及其强类型属性的任意列表从列表中查找项目。

这是我想调用该方法的方式:

var obj = new SomeObject() { ... } ;
var list = new List<SomeObject>() { ... };

// Find similar objects
list.Find(obj, x => x.Id,y => y.Description);

这种安排可行吗?

FirstOrDefault 将像下面的评论一样工作。但是,我正在寻找一种在可能不是简单查找的不同场景中使用该模式的方法。

【问题讨论】:

  • 已经存在一个名为Find 的扩展方法,正如建议的那样,FirstOrDefault 也可以轻松完成相同的工作。如果您需要在列表中找到满足您条件的所有元素,请使用Where 扩展方法
  • 您是在尝试根据匹配的属性值查找单个结果还是多个结果?
  • 除了我在这里给出的简化问题之外,我更感兴趣的是如何在其他场景中使用或不使用这种模式。一个例子可能是查找一些类型信息并根据给定的属性打印。
  • 我更新了我的答案。看看它是否是您正在寻找的东西。如果不是,你能解释一下吗?

标签: c# linq generics extension-methods


【解决方案1】:

你可以这样做

public static T Find<T>(this IEnumerable<T> source, params Func<T,bool>[] condition)
{
    return source.FirstOrDefault(o => condition.All(f => f(o))); // use All for && or use Any for ||
}

并使用它

var item = list.Find(x=> x.Id == obj.Id,x=> x.Description == obj.Description);

如果您想通过将属性转换为对象来更普遍地工作,您可以使用 Object。但这会有点慢,您必须注意,必须覆盖 自定义类型Equals 方法才能使其工作。

public static T Find<T>(this IEnumerable<T> source, T obj, params Func<T, object>[] condition)
{
    return source.FirstOrDefault(o => condition.All(f => f(o).Equals(f(obj))));
}

那么你就可以这样称呼它了。

var item = list.Find(obj, x => x.Id,y => y.Description);

如果您想退回所有类似商品,您可以使用Where。只需将FirstOrDefault 更改为Where 并将方法的返回类型更改为IEnumerable&lt;T&gt;

【讨论】:

  • 我理解你的逻辑,但我在考虑比较通用的东西,所以我可以传递参数。如果 C# 可以推断变量,那将是非常酷的。也许微软可以提供一个 params 概念。然后你可以像这样调用方法 public static DoSomething(o.Id, o.Description) 。
  • @jwize 你可以使用dynamic 类型,它的实际类型在运行时被评估。但它会慢得多,因为类型不是恒定的。
【解决方案2】:

在我看来,与仅使用普通的 Where 子句过滤您所追求的任何属性相比,您并没有节省大量时间/精力。

var findResults = list.Where(x => x.Id == obj.Id || x.Description == obj.Description);

【讨论】:

    【解决方案3】:

    也许你应该考虑这样处理:

    var myResult = from currentObject in mylist
                   where currentObject == mySingleObject // change it by your matching criterias linked by && or || (as in if ...)
                   // NB: you can also override the == operator in your object definition
                   // but as mentionned below, it won't work for generic types
                   select currentObject;
    

    【讨论】:

    • 运算符重载在不知道 T 的 Find 中不起作用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-03-05
    • 1970-01-01
    • 2019-05-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多