【问题标题】:Why don't anonymous types have an indexer property?为什么匿名类型没有索引器属性?
【发布时间】:2023-03-05 15:28:01
【问题描述】:

既然匿名类型无论如何都是编译器生成的,为什么不更进一步,使用索引器访问其属性的值,类似于 ExpandoObject,但使其静态编码。

一些背景: 我目前正试图在 microORM 中尽可能地提高性能,但有一件事让我印象深刻:对匿名类型的反思。

参数作为对象传入,虽然通常不需要是匿名类型。我必须使用反射来获取每个成员的名称和值,因为匿名类型实际上只是编译器生成的 POCO。

在 C# 中使用 ExpandoObject 和其他一些动态结构后,我发现自己缺少 Expando 的显式 IDictionary 接口实现。

【问题讨论】:

  • 匿名类型有一个非常独特的目的,它与一些 C# 程序员希望他们做的事情非常几乎没有关系。他们为 Linq 供电,仅此而已。试图让他们做得更多是失败的鲸鱼。性能与它完全无关。
  • 我很清楚他们目前不能这样做,并且您对创建构造的最初原因是正确的,但我不同意在 linq 以外的任何东西中使用匿名类型是“失败的鲸鱼” .它们现在是语言的重要组成部分。
  • 真正的失败者是匿名类型的成员只有“内部”访问权限。如果您在 Razor 中尝试此操作:@Html.Partial("~/Shared/DatePicker.cshtml", new {id="ctrl1",mode="yearonly"}),它将失败并出现绑定错误,因为 Razor 引擎无法访问匿名类型的属性,即使模型是使用 @model 动态声明的。模型存在并且属性在调试器中可见,但 Razor 实现的默认页面绑定器不会尝试使用反射访问属性。即使您改为传递 ExpandoObject,它仍然会以类似的方式失败。

标签: c# compilation anonymous-types


【解决方案1】:

如果您查看definition of ExpandoObject,您会发现它实现了 IDictionary 和 IDynamicMetaObjectProvider(让您的代码挂接到 DLR 的神奇部分)。基本上它带来了Python dictionaries 的强大功能(Python 中的字典可以通过基于字符串的“索引器”或使用 . 访问器来访问,就好像它是直接在对象上定义的属性(甚至函数)一样)。

匿名类型不是动态的。它们在编译时被解析。你不能增加或减少他们的定义。

一般来说,反射 API 没有“字典”类型的访问,尽管我不明白为什么你不能实现它。 IDictionary 是一个接口...您可以创建一个 IDictionary 实现,该实现采用一个对象并使用对该对象的反射来解析索引器请求。

【讨论】:

    【解决方案2】:

    它们没有索引器,因为您将参数作为基本 Object 引用类型传入。不能合理地假设您可以使用在方法协定中未定义的接口上定义的方法。

    【讨论】:

    • 是的,它们作为对象传入,但如果匿名类型实现了接口,则执行“is”或“as”操作将起作用,从而暴露合同。
    • 错了,我猜。正如汉斯在对原始问题的评论中所建议的那样,这不是您应该使用的东西。正如您所说,匿名类型是 POCO 对象,ExpandoObject 是实现 IDictionary、ICollection、Enumerable、IEnumerable、INotifyPropertyChanged 和 IDynamicMetaObjectProvider 的密封类。如果您需要这些接口,ExpandoObjects 会很棒,但如果您不需要这些接口,那么您需要为不需要的东西支付大量开销。如果需要,使用 'is' 或 'as' 检查 ExpandoObject。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-10-15
    • 1970-01-01
    • 2013-04-21
    • 2015-05-24
    • 2018-07-21
    • 1970-01-01
    相关资源
    最近更新 更多