繁体   English   中英

限制泛型子类方法在c#中可以接受的类型

[英]Restrict types a generic subclass method can accept in c#

如果标题含糊不清或者这是重复,我会道歉。 我今天花了大量时间阅读仿制药,并寻找类似的情况无济于事。

我正在写一个小游戏引擎。 其中一个方面是“单位”携带资源的能力。 有些单位可以携带任何资源,有些单位只能携带某些专门资源。 为此,我有以下结构:

Resource基类:

public abstract class Resource
{
    private int _count;

    public int Count
    {
        get { return _count; }
        set { _count = value; }
    }

    public Resource(int resourceCount)
    {
        _count = resourceCount;
    }
}

然后是Resource专业化Wood

public class Wood : Resource
{
    public Wood(int resourceCount) : base(resourceCount)
    {
    }
}

然后我有我的通用ResourceStore

public class ResourceStore<T> : IResourceStore where T : Resource
{
    private List<Resource> _store;

    public IEnumerable<Resource> Store { get { return _store; } } 

    public void AddResource(Resource resource)
    {
        _store = new List<Resource>();
        _store.Add(resource);
    }
}

最后是一个专门的商店WoodStore ,其中AddResource方法应该只接受Wood

public class WoodStore : ResourceStore<Wood>
{

}

为了完整性, IResourceStore接口由任何可以充当资源存储的东西实现:

public interface IResourceStore
{
    void AddResource(Resource resource);
}

如果我运行一个小的控制台应用程序并执行以下操作,我会在尝试将Wheat添加到WoodStore时出现错误。 但它没有,实际上输出显示WoodStore现在包含木材和小麦。 这是控制台应用程序:

class Program
{
    static void Main(string[] args)
    {
        WoodStore store = new WoodStore();
        store.AddResource(new Wood(10));
        store.AddResource(new Wheat(5));

        foreach (Resource resource in store.Store)
        {
            Console.WriteLine("{0} {1}", resource.GetType(), resource.Count);
        }

        Console.ReadLine();
    }
}

最后, Wheat只是为了完整性,尽管没有什么特别之处:

public class Wheat : Resource
{
    public Wheat(int resourceCount) : base(resourceCount)
    {
    }
}

我显然在这一棵树上咆哮着,并且非常感谢我如何限制WoodStore只接受Wood。 最终会有很多不同的商店会有一定的限制,我正在寻找一种方法来处理这个问题。

非常感谢。

你的界面需要是通用的,你需要在后备存储中使用TAddResourcenew List也不是我想要的:

public interface IResourceStore<T> where T : Resource
{
    void AddResource(T resource);
}

public class ResourceStore<T> : IResourceStore<T> where T : Resource
{
    private List<T> _store = new List<T>();

    public IEnumerable<T> Store { get { return _store; } } 

    public void AddResource(T resource)
    {
        //_store = new List<T>(); //Do you really want to create a new list every time you call AddResource?
        _store.Add(resource);
    }
}

首先,正如你在开头所说的那样,标题与问题内容的关系并不那么明确。

ha的第一个简单基本答案有多个商店,每个商店都有限制,即使在允许操作资源的方法中也使用通用过滤器

public class ResourceStore<T> : IResourceStore where T : Resource 
{ 
         private List<T> _store;

    public IEnumerable<T> Store { get { return _store; } } 

    public void AddResource(T resource)
    {
        _store = new List<T>();
        _store.Add(resource);
    }

    void IResourceStore.AddResource(Resource resource)
    {
        //possible excepion here for type mismach!
        AddResource(resource as T);
    }
}

如果你注意到没有显式可见性应用程序的另一种方法,该方法是显式的IResourceStore接口实现,这是必需的,但我可以建议不是一个好的设计解决方案。

首先,如果抽象存储的概念是通用的,即使接口应该是通用的,如果您的需求没有明确需要,那么接口应该是具有通用限制的抽象类的相同泛型:

public interface IResourceStore<T> 
   where T : Resource
{
   void AddResource(T resource);
}

同样,可枚举支持应包含在接口中,以便抽象类支持它。 所以最终的代码应该类似于:

public class ResourceStore<T> : IResourceStore<T> where T : Resource
{
    private List<T> _store;

    public IEnumerable<T> Store { get { return _store; } }

    public void AddResource(T resource)
    {
        _store = new List<T> {resource};
    }

    public IEnumerator<T> GetEnumerator()
    {
        return Store.GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
}

public interface IResourceStore<T> : IEnumerable<T>
   where T : Resource
{
        void AddResource(T resource);
}

public abstract class Resource
{
    public int Count { get; set; }

    protected Resource(int resourceCount)
    {
        Count = resourceCount;
    }
}

希望这可以帮助。 我还应用了一些小代码优化。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM