【问题标题】:Pass generic EquaityComparer with SequenceEqual使用 SequenceEqual 传递泛型 EquaityComparer
【发布时间】:2016-07-15 14:58:30
【问题描述】:

为了更清楚,我正在更新问题:

我正在尝试构建一个用于过滤记录的 LINQ 表达式。

例如:

public string Name {get; set;}
public List<string> Score { get; set; }

 public Student(string name, List<string> list=null)
 {
     Name=name;
     Score=list;
 }

我有这些学生的名单:

    List<Student> listStudent = new List<Student>
              { new Student("Jane", new List<string>{"A","B"}),
                new Student("Joe", new List<string>{"B", "C"}),
                new Student("Jack")};

现在,我只想获取分数与给定列表匹配的学生:

List<string> scoresToCompare=new List<string>{"B", "C"};
var Result= listStudent.Where(x =>x.Score!=null ? scoresToCompare.SequenceEqual(x.Score,  new StringComparer<string>()): false)

我的 StringComparer 在比较时忽略大小写:

class StringComparer<T> : IEqualityComparer<T>
{
    public bool Equals(T x, T y)
    {
        //Check whether the compared objects reference the same data.
        if (Object.ReferenceEquals(x, y)) return true;

        //Check whether any of the compared objects is null.
        if (Object.ReferenceEquals(x, null) || Object.ReferenceEquals(y, null))
            return false;

        //Ignore case when comparing.
        return x.ToString().Equals(y.ToString(), StringComparison.InvariantCultureIgnoreCase);
    }

    public int GetHashCode(T item)
    {
        //Check whether the object is null
        if (Object.ReferenceEquals(item, null)) return 0;

        //Get hash code for the Name field if it is not null.
        int hashCode = item == null ? 0 : item.GetHashCode();

        //Calculate the hash code for the product.
        return hashCode;
    }

}

现在,直到运行时我才会知道 List 中项目的类型,所以我正在尝试构建一个表达式来实现相同的结果。

Type typeOfItemInList = listStudent.FirstOrDefault().GetType(); //Not the exact code, but thats how I get the type

如何使用 stringComparer 调用 sequenceEqual 方法?

var callSequenceEqualMethodWithComparer= Expression.Call(typeof(System.Linq.Enumerable), "SequenceEqual", new Type[] typeOfItemsInList }, new Expression[] { listToCompare1,  listToCompare2, **stringComparer**});

最后我还需要做一个 Expression.Condition 来检查 x.Score !=null 是否通过:

Expression.Condition(Expression.NotEqual(expressionOfList1, Expression.Constant(null)), Expression.Convert(Expression.Call(callSequenceEqualMethodWithComparer, expressionOfList1, expressionOdList2), typeof(bool)), Expression.Default(typeof(bool)) );

提前致谢!

【问题讨论】:

  • 使用未显示的变量从那些孤立的语句中很难判断您在做什么。请提供minimal reproducible example 预期结果和实际结果。 (但是不,您根本不应该自己调用 Equals - 当您已经在步骤 1 中通过比较器时,不清楚您希望在步骤 2 中做什么......)
  • 你为什么要创建一个 Equality 比较器而不是只使用 SequenceEqual ?
  • 因为 SequenceEqual 区分大小写。我需要比较不区分大小写

标签: c# linq generics lambda linq-expressions


【解决方案1】:

您可以通过调用Expression.New() 来创建一个创建对象的表达式。

要获取类型,您可以使用typeof(StringComparer&lt;&gt;) 获取StringComparer&lt;T&gt; 的开放泛型类型,然后在其上调用MakeGenericType() 以获取封闭类型,例如StringComparer&lt;string&gt;

放在一起:

Expression.New(typeof(StringComparer<>).MakeGenericType(typeOfItemInList))

【讨论】:

  • svick - 工作就像一个魅力 - 非常感谢!我用这样的字符串比较器调用了 SequenceEqual: var callSequenceEqualMethodWithComparer= Expression.Call(typeof(System.Linq.Enumerable), "SequenceEqual", new Type[] typeOfItemsInList }, new Expression[] {listToCompare1, listToCompare2, Expression.New (typeof(StringComparer).MakeGenericType(typeOfItemInList))});这很好用。我只需要稍微修改前面的代码就可以调用带有 3 个参数的 SequenceEqual 方法。再次感谢。
猜你喜欢
  • 2016-02-12
  • 2011-08-26
  • 1970-01-01
  • 1970-01-01
  • 2014-06-08
  • 2021-04-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多