【问题标题】:Uses of KeyedByTypeCollection in .Net?.Net 中 KeyedByTypeCollection 的用途?
【发布时间】:2010-09-24 17:29:42
【问题描述】:

在查看 .net 中的通用集合时,我发现了 KeyedByTypeCollection。虽然我使用过它并知道如何使用它,但我不知道它在哪种情况下有用。

我阅读了ServiceProvider, cache etc. done with generics without cast,但没有得到太多。

我认为,它被包含在 .Net 框架中一定是有原因的。任何使用过 KeyedByTypeCollection 的机构都可以向我解释他们为什么使用它,或者任何机构,如果他们知道可能在哪种情况下可以使用它,可以向我解释。

还有其他语言支持这种类型的集合吗?

【问题讨论】:

    标签: .net .net-3.5


    【解决方案1】:

    AFAIK,当KEY 是要存储的VALUE 的类型时,此通用集合仅用作KeyedCollection<KEY,VALUE> 的简单包装器。

    例如,如果你想实现工厂返回单例,使用这个集合非常方便:

    public class Factory<T>
    {
        private readonly KeyedByTypeCollection<T> _singletons = new KeyedByTypeCollection<T>();
    
        public V GetSingleton<V>() where V : T, new()
        {
            if (!_singletons.Contains(typeof(V)))
            {
                _singletons.Add(new V());
            }
            return (V)_singletons[typeof(V)];
        }
    }
    

    这个简单工厂的用法如下:

        [Test]
        public void Returns_Singletons()
        {
            Factory<ICar> factory = new Factory<ICar>();
            Opel opel1 = factory.GetSingleton<Opel>();
            Opel opel2 = factory.GetSingleton<Opel>();
    
            Assert.IsNotNull(opel1);
            Assert.IsNotNull(opel2);
            Assert.AreEqual(opel1, opel2);
        }
    

    KeyedByTypeCollection&lt;T&gt; 的另一种用法是在服务定位器中...

    【讨论】:

    • 感谢您在这里提供的良好使用。
    • 为什么工厂要退回单身人士?
    【解决方案2】:

    “单件工厂”是解决单件问题的不同方法。

    主要有三种方法:

    1. 在每个类中实现 CurrentInstance 属性 - 意味着大量重复代码。哪个不好。

    2. 实现 Singleton&lt;T&gt; 基类 - 意味着您可以拥有 class A : Singleton&lt;B&gt;,这显然是错误的。

    3. 实现SingletonFactory - 这是有据可查的。大约 12 个月前我想到了它,坦率地说,我很惊讶地发现它在 Java 世界中是一个覆盖面非常广的主题。我为我当前的客户端编写的那个没有接口限制,并且是静态的,这意味着它在集合周围有一个锁以确保线程安全。如果不将其设为静态,您可能会得到两个相同类型的单例,它们是不同的对象。

    【讨论】:

      【解决方案3】:

      在分析这个类时,我认为它完全无关紧要。使用基类KeyedCollection,编写GetKeyForItem方法返回Item参数的Type。

      KeyedByTypeCollection 上定义了四种无关的方法(FindFindAllRemoveRemoveAll)。 Find、FindAll 和 RemoveAll 没有基本的 KeyedCollection 实现。 Remove 确实存在于基类中。

      KeyedByTypeCollection 中所有这四种方法的第一个问题是它们对基本集合执行连续搜索以查找项目。为什么不直接使用来自KeyedCollection 的索引器来检索适当的项目?

      其次,FindAllRemoveAll 只会找到 1 项(如果集合中存在一项) - 因为根据定义,集合中只会存在指定类型的一项(哦,FindAll将连续读取集合中的所有元素,即使它在开头找到匹配的元素)。因此,FindAllRemoveAll 将在查找/删除 0 或 1 个项目之前读取集合中的所有项目。同样,为什么不使用索引器或 Remove 的基本版本来执行所需的过程?

      这个类的第二个问题是它不是被设计成一个基类(换句话说,除非你知道方法的内部是如何编写的,否则不要从它继承)。在应该使用 GetKeyForItem 方法的地方没有调用它,因此,如果您重写 GetKeyForItem 方法,您还必须重写其他几个方法才能正确获取 Collection 的密钥。

      【讨论】:

        猜你喜欢
        • 2019-11-12
        • 2019-12-31
        • 2011-03-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-11-06
        • 1970-01-01
        • 2019-11-11
        相关资源
        最近更新 更多