簡體   English   中英

從變量類型獲取默認相等比較器?

[英]Get Default Equality Comparer from Variable Type?

有沒有辦法獲得給定類型的默認比較器,其中類型是可變的並且僅在運行時知道? 考慮以下:

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

這顯然不能編譯,但如果編譯了,則comparer的值應該等於EqualityComparer<string>.Default

我能想到的唯一方法是制作一個可以通過反射調用的“盒裝”比較器(見下文)。 這行得通,但它很麻煩。 有沒有更好的方法來做到這一點?

澄清一下,由於反射,這不是一個好主意,但為什么我需要它?

有問題的算法是大型遺留搜索 API 的一部分。 消費者將對象列表(例如List<Person> )傳遞給 API 內部創建類型特定的索引(使用反射),以便調用者可以搜索 object 中的任何字段(例如,可能是姓氏)。 這通常不是必需的,但在我正在服務的用例中,我們正在搜索非常大的集合與其他非常大的集合。 為此目的,數據庫存儲過程可能更好。 但是現在我需要修補這個遺留的 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>在內部為每個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(通常您傳遞包含該屬性的 object)。

同樣,此代碼不是推薦的方法。 可讀性、可重用性、維護和錯誤處理選項並未真正考慮。 這個例子只是展示了一種更簡單的方法來獲得所需的東西,而無需引入額外的類。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM