【问题标题】:Indexers in generic Interface通用接口中的索引器
【发布时间】:2015-12-19 16:43:44
【问题描述】:
public interface IRepository <T>  where T : EntityBase
{
    T FindBy(object key);
    void Add(T item);
    T this[object key] { get; set; }
    void Remove(T item); 
}

这是“Domain-Driven-Design .NET C#”一书的作者给出的通用存储库接口的代码示例。在没有解释的情况下,作者在接口T this[object key] { get; set; } 中放置了一个索引器,其中对象键是对象ID(就整个系统的身份而言)。作者指出,放置索引器是为了强调存储库应该模拟内存中的对象集合。所以我的问题是:将索引器放入界面有什么好处吗?任何链接、视频、书籍、教程都会对我有很大帮助。谢谢你。

【问题讨论】:

  • “而不是 IEnumerable 或 List”是什么意思?您能否展示这些替代索引器的方法?
  • 使用索引器和返回IEnumerableList 是不同的,因为T 不是一个集合。我想在给定一个已知键时使用索引器,我可以检索它的值,或者给定一个键集它的值。也许详细说明你的意思而不是要求教程。
  • 对于不相关的信息,我深表歉意。并不是要把 IEnumerable 或 List 放在那个上下文中。我在翻译中迷路了。我将编辑问题。感谢您的耐心等待。
  • 呃,如果你需要一个索引器,你就放一个。我不明白这个问题。

标签: c# .net generics interface


【解决方案1】:

作者指出,将索引器放在那里是为了强调一个 存储库应模拟内存中的对象集合。

老实说,我从来没有听说过这个概念。我在很多项目上看到了存储库模式的实现,我们从未在那里使用过索引器。事实上,索引器将用于按 ID 获取项目,这将复制您的 T FindBy(object key);

所以,我的总结:在大多数情况下,存储库确实提供了对对象集合的访问,但我认为向其中添加索引器没有任何价值。我宁愿专注于您的应用程序所需的事务/查询。


我通常使用BaseRepository : IRepository&lt;T&gt; 实现通用IRepository&lt;T&gt;,然后实现特定存储库UsersRepository : BaseRepository&lt;User&gt;, IUsersRepository,其中IUsersRepository 接口包含用于用户查询和命令的特定方法。

【讨论】:

    【解决方案2】:

    在这种情况下,索引器用于检索给定对象的键(而不是它在集合中的索引)。在 System.Collections.Generic 中的标准通用接口之外,IDictionary&lt;TKey, TValue&gt; 是包含该功能的接口。但是,该接口包含更多功能,这些功能并非由存储库自然公开。

    当然,可以实现这些其他方法,但它们效率不高。而提供非高效 API 无疑是邀请 API 用户编写低效代码的可靠方式。

    【讨论】:

    • “在标准通用接口之外,IDictionary&lt;TKey, TValue&gt; 是包含该功能的接口。” - 根据您所说的“标准通用接口”,许多其他接口也提供索引器。
    • @O.R.Mapper 编辑并更清楚地表明我的意思是 System.Collections.Generic 接口。
    • 那么IList&lt;T&gt;呢?它也有一个索引器。
    • @O.R.Mapper 查看我编辑的答案,该索引器用于索引,而不是对象的键。
    【解决方案3】:

    作者指出,放置索引器是为了强调存储库应该模拟内存中的对象集合。

    这听起来是一个合理的理由。通过“强调”一词,它指向一个重要方面:索引器不一定要添加任何功能,它也可以简单地用于提高结果代码的可读性。

    假设某个对象有一个名为Resources 类型为IRepository&lt;Something&gt; 的属性,没有索引器,则只能按如下方式检索特定项目:

    var theItem = myObject.Resources.FindBy(someKey);
    

    使用索引器,也可以进行以下操作:

    var theItem = myObject.Resources[someKey];
    

    在某种程度上,这是个人喜好问题,但第二个版本可能更直观地被识别为仅从列表之类的东西中检索,而不是任意参数化的方法调用。

    【讨论】:

      【解决方案4】:

      将索引器放入界面有什么好处吗?

      这是主观的。如果您通过一些找到更有意义的定位对象,为什么不呢?

      使用索引器时的主要问题是它们可能会过载。虽然您的界面定义了一个索引器来获取对象 by id(其中 idobject...我会将对象 id 转换为泛型类型...),按照建议的模式,如果您定义的索引器比通过标识符检索域对象的索引器多,则可能会失去索引器的含义。

      例如:

      T this[object key] { get; set; }
      T this[T someObject] { get; set; }
      T this[int whoKnowsWhatIsIntegerHere] { get; set; }
      

      归根结底,实现索引器取决于您,它不会或多或少地强调以正确方式实现存储库的方式使用它们:存储库在域之间进行调解时很好和数据映射器将域对象转换为数据,反之亦然。。也就是说,这与它们的方法的名称或它们是否看起来像 IList&lt;T&gt; 无关......

      像收藏一样工作并不意味着看起来像收藏...

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-03-17
        • 2010-11-16
        • 1970-01-01
        • 2010-12-05
        • 2012-03-24
        相关资源
        最近更新 更多