Почему эти два анонимных типа не совпадают?

Может ли кто-нибудь сказать мне, почему эти два анонимных типа не совпадают?

{Name = "<>f__AnonymousType0`6" FullName = "<>f__AnonymousType0`6[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.Decimal, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.Double, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]"}

{Name = "<>f__AnonymousType0#1`6" FullName = "<>f__AnonymousType0#1`6[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.Decimal, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.Double, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]"}

ПОЯСНЕНИЕ: (не знаю, важно ли это, но один анонимный тип имеет символ #. о, #01)

У меня есть эти две части кода. В том же классе (сборка). Один возвращает один из анонимных типов выше, а другой возвращает другой. Однако оба оценивают одно и то же выражение.

Я сделал приведенные ниже сравнения (некоторые только для того, чтобы увидеть результат, хотя некоторые должны правильно возвращать false). Но все они возвращают false. (Возможно, я упустил некоторые из тех, что пробовал)

ms возвращает один из анонимных типов. resultOfSelect возвращает другой анонимный тип.

Примечание: methodArgumentStringContainingSelectStatement во втором фрагменте кода содержит то же выражение, что и строка.


'мс == результат выбора'

'ms.GetType() == результат выбора'

'ms.GetType().Equals(resultOfSelect.GetType())'

'ms.GetType() == resultOfSelect.GetType()'

И другие. Все Ложь

resultOfSelect debugView:

{Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable‹‹>f__AnonymousType0#1>}

ms debugView это:

{Microsoft.EntityFrameworkCore.Query.Internal.EntityQueryable‹‹>f__AnonymousType0>}

1-е утверждение:

   ' var ms =     (instanceContainingSelectMethod as IQueryable<Emar>).Select( nextEmarClassInstanceFromPreviousSelectMany => new { Schedule = nextEmarClassInstanceFromPreviousSelectMany.BEmem.Category.Substring(0, 1), Category = "0" + nextEmarClassInstanceFromPreviousSelectMany.BEmem.Category.Substring(1), Description = "", Year = nextEmarClassInstanceFromPreviousSelectMany.Month.Year, Time = nextEmarClassInstanceFromPreviousSelectMany.Actual_Time, Units = ((nextEmarClassInstanceFromPreviousSelectMany.BEmem.PurchDate ?? nextEmarClassInstanceFromPreviousSelectMany.BEmem.InServiceDate).Value.Year == nextEmarClassInstanceFromPreviousSelectMany.Month.Year)
? (nextEmarClassInstanceFromPreviousSelectMany.BEmem.SoldDate != null)
    ? (nextEmarClassInstanceFromPreviousSelectMany.BEmem.SoldDate.Value.Year == nextEmarClassInstanceFromPreviousSelectMany.Month.Year)
        ? (((12d - ((double)((nextEmarClassInstanceFromPreviousSelectMany.BEmem.PurchDate != null)
            ? (System.DateTime?)nextEmarClassInstanceFromPreviousSelectMany.BEmem.PurchDate.Value
            : nextEmarClassInstanceFromPreviousSelectMany.BEmem.InServiceDate).Value.Month)) + 1d) - (12d - ((12d - ((double)nextEmarClassInstanceFromPreviousSelectMany.BEmem.SoldDate.Value.Month)) + 1d))) / 12d
        : ((12d - ((double)(nextEmarClassInstanceFromPreviousSelectMany.BEmem.PurchDate ?? nextEmarClassInstanceFromPreviousSelectMany.BEmem.InServiceDate).Value.Month)) + 1d) / 12d
    : ((12d - ((double)(nextEmarClassInstanceFromPreviousSelectMany.BEmem.PurchDate ?? nextEmarClassInstanceFromPreviousSelectMany.BEmem.InServiceDate).Value.Month)) + 1d) / 12d
: (nextEmarClassInstanceFromPreviousSelectMany.BEmem.SoldDate != null)
    ? (nextEmarClassInstanceFromPreviousSelectMany.BEmem.SoldDate.Value.Year == nextEmarClassInstanceFromPreviousSelectMany.Month.Year)
        ? (12d - ((12d - ((double)nextEmarClassInstanceFromPreviousSelectMany.BEmem.SoldDate.Value.Month)) + 1d)) / 12d
        : 1d
    : 1d } );'

2-е заявление:

            'Func<IQueryable<Emar>, object> customSelectManyDelegate =

           await CSharpScript
             .EvaluateAsync<Func<IQueryable<Emar>, object>>(methodArgumentStringContainingSelectStatement, options);

         resultOfSelect =  customSelectManyDelegate(instanceContainingSelectMethod as IQueryable<Emar>);'

person K. Carter Sr.    schedule 05.03.2019    source источник
comment
Действительно, чтобы получить полезный ответ, вы должны добавить контекст к своему вопросу. Покажите минимально воспроизводимый пример. Где вы создали эти типы? Очевидно, что компилятор сгенерировал два разных типа (отсюда и два разных имени). Но без кода, который заставил компилятор это сделать, мы ничего не можем об этом сказать.   -  person René Vogt    schedule 05.03.2019
comment
Непонятно, почему какой-либо из этих тегов упоминается в вопросе, кроме, может быть, Roslyn. Возможно, вы используете EF и linq, но какое это имеет отношение к вопросу?   -  person    schedule 05.03.2019
comment
afaik компилятор генерирует анонимные типы на сборку. Так может вы их создавали в разных сборках?   -  person René Vogt    schedule 05.03.2019
comment
Может быть, вы могли бы сказать нам, почему вы думаете, что они одинаковы? «Имя» и «Полное имя» разные, так почему вы ожидаете, что они будут идентичными?   -  person Sean    schedule 05.03.2019
comment
@RenéVogt Я могу ошибаться, но я думал, что на самом деле это на модуль; теперь предоставлено... большинство сборок имеют только 1 модуль, но...   -  person Marc Gravell    schedule 05.03.2019
comment
@MarcGravell ну, я не знаю этого до этих деталей, различие между модулями и сборками никогда не было необходимо при работе в течение всего дня;)   -  person René Vogt    schedule 05.03.2019
comment
Хорошо, я отредактировал вопрос. Спасибо   -  person K. Carter Sr.    schedule 05.03.2019
comment
@RenéVogt Хммм, просто смотрю на твои ответы. На ум приходит вопрос. Делает ли анонимный тип, возвращаемый EvaluateAsync (API сценариев Roslyn) во втором операторе, и анонимный тип, возвращаемый оператором select 1st, из двух разных сборок, даже если они находятся в одном и том же фрагменте кода?   -  person K. Carter Sr.    schedule 06.03.2019
comment
Вы используете CSharpScript.EvaluateAsync. Каждая оценка в скрипте C# логически представляет собой отдельную сборку. Анонимные типы (по реализации, а не по спецификации) уникальны для каждой сборки.   -  person Matt Warren    schedule 08.03.2019


Ответы (2)


Анонимные типы на самом деле предназначены только для использования в контексте одного метода или возможно в некоторых сценариях отражения, где важна только форма, а не тип.

Итак: спрашивать, почему тип отличается , уже нарушает цель языковой функции. Что касается почему они разные: вероятно, разные сборки или модули. В частности, это относится к веб-проектам, где представления компилируются позже основного кода.

Но: не полагайтесь на это равенство, в принципе. Это не гарантировано. Если вам небезразличен тип (и чему он равен), то ваши варианты включают:

  • объявить собственный формальный тип и использовать его - лучший вариант
  • использование кортежей значений (ValueTuple<...>, но с первоклассной языковой поддержкой, включая псевдо-имена, которые распространяются от вызываемого объекта к вызывающему, но не от вызывающего объекта к вызываемому)
  • используя кортежи (Tuple<...>)

Использование анонимных типов на самом деле не фигурирует в списке.

person Marc Gravell    schedule 05.03.2019
comment
Может ли мой ответ / вопрос @RenéVogt быть разницей. - person K. Carter Sr.; 06.03.2019
comment
@К.КартерСр. довольно сложно сказать без конкретного воспроизведения, но еще раз подчеркну, что это не стоит знать: вы не предназначены заботиться о равенстве типов, если вы (по определению) уже не может заботиться о типе - person Marc Gravell; 06.03.2019
comment
Марк Гравелл. Я отмечаю это как принятое, хотя @René Vogt сказал это первым, и я все равно не вижу возможности пометить комментарий как принятый. Мэтт Уоррен ответил более подробно. Спасибо, Мэтт Уоррен. Кроме того, Марк, взгляните на мой вопрос stackoverflow.com/questions/55056318/ . Это также в том же коде и связано. - person K. Carter Sr.; 09.03.2019

Мэтт Уоррен написал этот комментарий:

Вы используете CSharpScript.EvaluateAsync. Каждая оценка в скрипте C# логически представляет собой отдельную сборку. Анонимные типы (по реализации, а не по спецификации) уникальны для каждой сборки. — Мэтт Уоррен

person Community    schedule 15.07.2020