从变量类型获取默认相等比较器?

Get Default Equality Comparer from Variable Type?

有没有办法获得给定类型的默认比较器,其中类型是可变的并且仅在运行时已知?考虑以下因素:

var RT = typeof(string);
var comparer = EqualityComparer<RT>.Default;

这显然不能编译,但如果编译通过,comparer 的值应该等于 EqualityComparer<string>.Default

我能想到的实现此目的的唯一方法是制作一个“盒装”比较器,您可以通过反射调用它(见下文)。这行得通,但是很麻烦。有没有更好的方法来做到这一点?

澄清一下,由于反射,这不是一个好主意,但为什么我需要它?

相关算法是大型遗留搜索的一部分 API。消费者将对象列表(例如,List<Person>)传递给 API,在内部创建类型特定的索引(使用反射),以便调用者随后可以搜索该对象中的任何字段(例如,也许是姓)。这通常不是必需的,但在我提供服务的用例中,我们正在针对其他非常大的集合搜索非常大的集合。数据库存储过程可能更适合此目的。但是现在我需要修补这个遗留问题 API 以支持用户定义的比较算法,并且还支持用户选择不提供任何比较算法的情况,在这种情况下我只知道运行时类型 RT .

// Example usage
// Assume "RT" is a Type known only at runtime (e.g., typeof(string))
var box = typeof(BoxedComparer<>);

var generic = box.MakeGenericType(RT);
var specific = (IBoxedComparer) Activator.CreateInstance(generic);

// Now with specific you can get the equality comparer for the runtime type (RT)
var comparer = specific.GetEqualityComparer();

public interface IBoxedComparer
{
   // You need the interface to allow a "typeless" cast
   EqualityComparer GetEqualityComparer()
}

public BoxedComparer<T> : IBoxedComparer 
{
   public EqualityComparer GetEqualityComparer() { return EqualityComparer<T>.Default; }
}

致未来的网络搜索者:

反射不是推荐的方法。可能重构是有序的。例如,不清楚 var comparer 一旦以这种方式通过反射创建后将如何实际使用。

为了减轻性能问题,您可以在创建比较器时缓存它们,就像 EqualityComparer<T>source 在内部对每个 T 所做的一样。但是这样你的代码就会变得更加混乱。

也就是说...

一种更简单的单行方式来完成反射:

var comparer = typeof(EqualityComparer<>).MakeGenericType(RT).GetProperty("Default", BindingFlags.Public | BindingFlags.Static).GetValue(null);

其中 RT 是我们在编译时不知道的运行时 Type 实例。

要求:

using System.Collections.Generic;
using System.Reflection;

请注意,当通过反射访问 static 字段或 属性 时,预计会将 null 传递给 GetValue/SetValue(通常情况下您传递包含 属性).

的对象

同样,此代码不是推荐的方法。没有真正考虑可读性、可重用性、维护和错误处理选项。这个例子只是展示了一种更简单的方法来获得所需的东西而无需引入额外的 类.