为什么这两种匿名类型不相同?

时间:2019-03-05 16:23:16

标签: entity-framework linq roslyn anonymous-types ef-core-2.0

谁能告诉我为什么这两种匿名类型不一样?

{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 == resultOfSelect'

'ms.GetType()== resultOfSelect'

'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>}

第一个陈述:

   ' 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 } );'

第二条陈述:

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

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

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

2 个答案:

答案 0 :(得分:7)

匿名类型实际上仅打算在单个方法的上下文中使用,或者可能在某些反射情况下,其中形状很重要,而不是类型。

所以:问为什么类型不同已经违反了语言功能的意图。至于为什么,它们是不同的:可能是不同的程序集或模块。这尤其适用于Web项目,其视图的编译要晚于主要代码。

但是:基本上,不要依赖于这种平等。不能保证。如果您关心类型是什么(以及它等于什么),那么您的选择包括:

  • 声明自己的正式类型并使用它-最佳选择
  • 使用值元组(ValueTuple<...>,但具有一流的语言支持,包括从被呼叫者传播到呼叫者但不从呼叫者传播到被呼叫者的伪名称)
  • 使用元组(Tuple<...>

使用匿名类型并没有真正出现在列表中。

答案 1 :(得分:0)

马特·沃伦(Matt Warren)发表了此评论:

您正在使用CSharpScript.EvaluateAsync。从逻辑上讲,C#脚本中的每个评估都是其自己的程序集。每个程序集的匿名类型(通过实现而不是规范)是唯一的。 –马特·沃伦(Matt Warren),19年3月8日在19:17