Почему при сбросе этого объекта JObject возникает исключение AmbiguousMatchException в LINQPad?

Когда я запускаю этот код в LINQPad, используя JSON.NET:

var x = JObject.Parse(
@"{
  ""data"" : [ {
    ""id"" : ""bbab529ecefe58569c2b301a"",
    ""name"" : ""Sample Name"",
    ""group"" : ""8b618be8dc064e653daf62f9"",
    ""description"" : ""Sample Name"",
    ""payloadType"" : ""Geolocation"",
    ""contract"" : ""a9da09a7f4a7e7becf961865"",
    ""keepAlive"" : 0
  } ]
}");

x.Dump();

AmbiguousMatchException выбрасывается при попытке вывести проанализированный JSON в окно вывода LINQPad. Зачем? Насколько я могу судить, это вполне законный JSON. http://jsonlint.com/ говорит, что это тоже верно.

1 ответ

Решение

Это проблема с тем, как .Dump() реализовано скорее всего.

Если вы проверите трассировку стека:

at System.RuntimeType.GetInterface(String fullname, Boolean ignoreCase)
at System.Type.GetInterface(String name)
at UserQuery.Main()
...

Мы можем видеть, что метод, бросающий исключение System.RuntimeType.GetInterface,

System.RuntimeType является одним из конкретных классов, используемых для представления Type объекты, когда отражение используется во время выполнения, поэтому давайте проверим Type.GetInterface(String, Boolean) который имеет это сказать:

AmbiguousMatchException
Текущий тип представляет тип, который реализует один и тот же универсальный интерфейс с различными аргументами типа.

Так выглядит GetInterface Метод вызывается с типом интерфейса, который реализован более одного раза, с различными T или аналогичные.

Чтобы вызвать ту же ошибку, просто замените x.Dump(); с этим:

var type = x.GetType().GetInterface("System.Collections.Generic.IEnumerable`1", true);

Это бросит то же исключение.

Вот более простой пример LINQPad, который показывает основную проблему:

void Main()
{
    var type = typeof(Problem).GetInterface("System.Collections.Generic.IEnumerable`1", true);
}

public class Problem : IEnumerable<string>, IEnumerable<int>
{
    IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable<string>)this).GetEnumerator();
    IEnumerator<string> IEnumerable<string>.GetEnumerator() => Enumerable.Empty<string>().GetEnumerator();
    IEnumerator<int> IEnumerable<int>.GetEnumerator() => Enumerable.Empty<int>().GetEnumerator();
}

Этот пример будет выбрасывать точно такое же исключение.


Вывод: нет ничего плохого ни в Json, ни в Json.Net, это проблема того, как LINQPad пытается выяснить лучший способ вывести объект в окно вывода.

Другие вопросы по тегам