LINQ to Objects中的自定义扩展方法,用于通过比较器返回匿名对象

时间:2013-06-13 08:56:49

标签: c# linq extension-methods

我读到当从LINQ to Objects查询中投射新的匿名对象时,投影对象将覆盖其EqualsGetHashCode方法,以便执行检查相等性的任何其他方法将正常工作

这让我觉得实现一个自定义运算符会生成T中传递的匿名版本,这对于避免在我的某些类中覆盖这些方法或创建自定义IComparers非常有用。

我想像这样使用它:

var newList = list.SelectWithComparer(s => new { s }).Union(List2);

首先,这是一个好主意吗?

其次,有可能吗?

我尝试了以下但无法获取编译代码:

public static class LINQExtensions
{
    public static IEnumerable<T> SelectWithComparer<T>(this IEnumerable<T> source)
    {
        return source.Select(s => new { s });          
    }
} 

编译错误是由于任何类型不再是原始T:

Error   5   Cannot implicitly convert type 'System.Collections.Generic.IEnumerable<AnonymousType#1>' to 'System.Collections.Generic.IEnumerable<T>'. An explicit conversion exists (are you missing a cast?)    

有人可以帮忙吗?

由于

1 个答案:

答案 0 :(得分:3)

匿名类型正确覆盖EqualsGetHashCode方法,但这些方法的实现又依赖于针对类型实现的EqualsGetHashCode方法为此对象定义的属性。

因此,例如,如果您定义这样的对象:

var anonym = new {A = 42, B = "XYZ"};

此匿名对象的EqualsGetHashCode的实施将调用Equals类型的GetHashCodeint(因为属性A类型为int),类型为string(因为属性B的类型为string)。

话虽如此,你想要实现的东西基本没用。实际上,如果您定义一个属性设置为对象s的匿名类型,例如:

var myAnonym = new { s };

要正确地作为词典/哈希表中的键,必须正确定义对象GetHashCode的{​​{1}}和Equals方法。
但如果它们是,那么将对象包装在匿名类中有什么意义呢?你已经可以在词典中使用它了:-)