Мне недавно пришлось кое-что отразить в .NET и наткнуться на странное поведение при сравнении определений универсальных типов.
Мне пришлось решить, является ли тип IDictionary<,>
, извлекая объект Type
от LINQ Expression
, поэтому я не смог использовать оператор is
, чтобы решить это.Кроме того, мне пришлось игнорировать параметры типа, иными словами, единственное, что было важно, это то, имел ли я дело с IDictionary<,>
любого типа ключ / значение.
Я начал со следующего:
// Just a placeholder, in my code I have no way of knowing that it
// is a Dictionary of string keys and string values or even that it
// is a dictionary at all.
typeof(Dictionary<string, string>)
.GetGenericTypeDefinition()
.GetInterfaces()
.Any(i => i == typeof(IDictionary<,>))
Я предполагал, что, поскольку я читал интерфейсы определения универсального типа, я получил бы определения универсального интерфейса.Еще более странным является то, что когда я вставил приведенный выше код в LINQPad, он вернул следующее:
typeof(IDictionary<TKey,TValue>) // it appears here
typeof(ICollection<KeyValuePair<TKey,TValue>>)
typeof(IEnumerable<KeyValuePair<TKey,TValue>>)
typeof(IEnumerable)
typeof(IDictionary)
typeof(ICollection)
typeof(IReadOnlyDictionary<TKey,TValue>)
typeof(IReadOnlyCollection<KeyValuePair<TKey,TValue>>)
typeof(ISerializable)
typeof(IDeserializationCallback)
Однако по какой-то причине сравнение в методе Any
не удалось ни для одного из этих элементов.Однако, если я получу определения общих типов для самих интерфейсов, например, так:
typeof(Dictionary<string, string>)
.GetGenericTypeDefinition()
.GetInterfaces()
.Select(i => i.IsGenericType ? i.GetGenericTypeDefinition() : i)
.Any(i => i == typeof(IDictionary<,>))
, тогда он вернет true
, как и должно быть.
Почему это так?Разве интерфейсы, возвращаемые методом .GetInterfaces()
при вызове определения общего типа, уже не являются самими определениями общего интерфейса?Если да, то каково объяснение, что когда я проверяю возвращенные интерфейсы в LINQPad, они кажутся общими определениями типов?
Я полагаю, это связано с тем фактом, что параметры типа интерфейса могут быть полностью независимы отобобщенные аргументы разработчика, например:
public class MyGenericType<TKey, TValue> : ISomeInterface<object> ...
, но все же выглядит странным, что возвращенные объекты Type
, похоже, не отражают такой случай (как я ожидал в этом конкретном примере) и из«выглядит», они выглядят как определения общих типов, но не идентифицированы как таковые.