首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何定义泛型类型的KeyedCollection而不指定键类型

如何定义泛型类型的KeyedCollection而不指定键类型
EN

Stack Overflow用户
提问于 2015-03-12 10:11:18
回答 1查看 566关注 0票数 0

我有一个具有指定类型键的泛型类,我希望创建该类的KeyedCollection(Of )。我认为这个代码更清楚我的话。

问题是是否可以重写代码,这样就可以在不指定键类型(int或整数)的情况下定义MyEnities类。

C#

代码语言:javascript
复制
public abstract class Entity<TPrimKey>
{public abstract TPrimKey Key { get; set; }    }

public class Entities<TPrimKey, TItem> : ObjectModel.KeyedCollection<TPrimKey, TItem> 
                       where TItem : Entity<TPrimKey>
{
    protected override TPrimKey GetKeyForItem(TItem item)
    {return item.Key;}
}

public class MyEntity : Entity<int>
{
    public override int Key { get; set; }
}

public class MyEnities : Entities<int, MyEntity>
{}

VB

代码语言:javascript
复制
Public MustInherit Class Entity(Of TPrimKey)
   Public MustOverride Property Key As TPrimKey
End Class

Public Class Entities(Of TPrimKey, TItem As Entity(Of TPrimKey))
    Inherits ObjectModel.KeyedCollection(Of TPrimKey, TItem)
    Protected Overrides Function GetKeyForItem(item As TItem) As TPrimKey
        Return item.Key
    End Function
End Class

Public Class MyEntity
    Inherits Entity(Of Integer)
    Public Overrides Property Key As Integer
End Class

Public Class MyEnities
    Inherits Entities(Of Integer, MyEntity)
End Class
EN

回答 1

Stack Overflow用户

发布于 2018-01-09 19:07:23

你差点就有了。以下是一个解决方案:

代码语言:javascript
复制
using System.Collections.ObjectModel;

public class Entity<TPrimKey>
{
    public TPrimKey Key { get; set; }
}

public class Entities<TPrimKey> : KeyedCollection<TPrimKey, Entity<TPrimKey>>
{
    protected override TPrimKey GetKeyForItem( Entity<TPrimKey> item )
    { return item.Key; }
}

public class MyEntity1 : Entity<int>
{
}

public class MyEntity2 : Entity<int>
{
}

public class MyEntities : Entities<int>
{
    public static void Test()
    {
        var entities = new MyEntities();

        var entity1 = new MyEntity1();
        entities.Add( entity1 );

        var entity2 = new MyEntity2();
        entities.Add( entity1 );
    }
}

要明确的是,这是一个稍微不同的方式思考你的目标。MyEntities仍然指定键类型int;任何想进入Entities<TPrimKey>的泛型方法。或者在EntitiesMyEntities之间创建一个泛型类MyEntities,以保存这些方法:

代码语言:javascript
复制
public abstract class MyEntitiesA<TPrimKey> : Entities<TPrimKey>
{
    // Methods that apply to all TPrimKeys go here.
    // Some methods may need to be abstract, and implemented
    // in each subclass, that has a concrete key (or at least a key with a constraint).
}

public class MyEntities : MyEntitiesA<int>
...

MyEntitiesA<TPrimKey>满足您的需求,而不指定键类型int。(在某个时候,您将创建具有具体类型的类和/或变量声明;“目标”是能够保持对所有可泛化描述的方法的泛型。)

你错过的是这一行:

代码语言:javascript
复制
    public class Entities<TPrimKey> : KeyedCollection<TPrimKey, Entity<TPrimKey>>

在那里,值的类型是根据键的类型定义的。这允许您定义GetKeyForItem,使其适用于所有TPrimKey

请注意,我包含了两个派生自Entity<int>的类,以显示该集合的全部功能。也可以通过Test()来展示它的作用。

您可能还会发现这些链接与以下相关:

“与数值类型匹配的泛型约束”

使用"where TPrimKey : class“

“模型的盲接口”

如果将集合基于interface而不是基类,则此技术甚至更强大。这允许将支持正确接口(在该键类型上)的任何类添加到集合中。在这里,我们可以看到,这允许我们定义泛型类EntityA<TPrimKey>EntityB<TprimKey>,其中有不同的子类:

代码语言:javascript
复制
using System.Collections.ObjectModel;

public interface IEntity<TPrimKey>
{
    TPrimKey Key { get; set; }
}

public class Entities<TPrimKey> : KeyedCollection<TPrimKey, IEntity<TPrimKey>>
{
    protected override TPrimKey GetKeyForItem( IEntity<TPrimKey> item )
    { return item.Key; }
}

public class EntityA<TPrimKey> : IEntity<TPrimKey>
{
    public TPrimKey Key { get; set; }
}

public class MyEntityA1 : EntityA<int>
{
}

public class MyEntityA2 : EntityA<int>
{
}

public class EntityB<TPrimKey> : IEntity<TPrimKey>
{
    public TPrimKey Key { get; set; }
}


public class MyEntityB1 : EntityB<int>
{
}

public class MyEntities : Entities<int>
{
    public static void Test()
    {
        var entities = new MyEntities();

        var entityA1 = new MyEntityA1();
        entities.Add( entityA1 );

        var entityA2 = new MyEntityA2();
        entities.Add( entityA2 );

        var entityB1 = new MyEntityB1();
        entities.Add( entityB1 );
    }
}

注意:您不必使用接口来创建多个泛型子类EntityAEntityB。我只是想说,如果你开始变得那么复杂,那就该考虑定义一个接口了,这样你就不会被“封闭”到一个基类中了。如果需要的话,定义接口可以轻松地重构类层次结构。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/29006890

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档