0

我有这个 :

public class CChainElement
{
    public CChainElement m_Prev, m_Next;
}

public class CChainList : IEnumerable
{
    public CChainElement m_First;

    internal void Add(CChainElement Element)
    {
        if (m_First != null)
            m_First.m_Prev = Element;

        Element.m_Next = m_First;
        m_First = Element;
    }
}

public class CEntity : CChainElement
{
}

public class CItem : CEntity
{
}

public class CTest
{
    void Test()
    {
        CChainList AllItem = new CChainList();
        CItem Item = new CItem();

        AllItem.Add(Item);

        CItem FirstItem = AllItem.m_First as CItem;
        CItem SecondItem = FirstItem.m_Next as CItem;
    }
}

我想切换到这样的东西:

public class CChainElement<T> where T : CChainElement<T>
{
    public T m_Prev, m_Next;
}

public class CChainList<T> : IEnumerable where T : CChainElement<T>
{
    public T m_First;

    internal void Add(T Element)
    {
        if (m_First != null)
            m_First.m_Prev = Element;

        Element.m_Next = m_First;
        m_First = Element;
    }
}

public class CEntity : CChainElement<CEntity>
{
}

public class CItem : CEntity
{
}

public class CTest
{
    void Test()
    {
        CChainList<CItem> AllItem = new CChainList<CItem>();
        CItem Item = new CItem();

        AllItem.Add(Item);

        CItem FirstItem = AllItem.m_First;  // Yeepee, no more "as CItem" ..! ;-)
        CItem SecondItem = FirstItem.m_Next;
    }
}

我得到的错误是CItem can't be converted to CChainElement<CItem>.

所以我的问题是:是否有任何约束public class CChainElement<T>,所以它会优雅地采用 CItem,即使它不直接从 CChainElement 继承?

我的目标显然是所有继承自CChainElement<T>能够与我的通用列表类一起列出的类,同时避免显式转换。

提前感谢您的帮助!

编辑:在我的完整项目中,CEntity 作为一个抽象类用于许多不同的事情(即:我可以通过它以与 Items 类似的方式操纵 Monsters),因此不能将其更改为通用的CEntity<T>.

4

2 回答 2

0

CChainElement不应该是通用的。唯一应该转向泛型的是CChainList.

public class CChainElement
{
    public CChainElement m_Prev, m_Next;
}

public class CChainList<T> : IEnumerable
   where T : CChainElement
{
    public T m_First;

    internal void Add(T Element)
    {
        if (m_First != null)
            m_First.m_Prev = Element;

        Element.m_Next = m_First;
        m_First = Element;
    }
}

public class CEntity : CChainElement
{
}

public class CItem : CEntity
{
}

public class CTest
{
    void Test()
    {
        CChainList<CItem> AllItem = new CChainList<CItem>();
        CItem Item = new CItem();

        AllItem.Add(Item);

        CItem FirstItem = AllItem.m_First;
        CItem SecondItem = FirstItem.m_Next;
    }
}
于 2012-09-25T07:29:23.200 回答
0

嗯,这是一个有趣的小问题。您需要进行以下更改:

public class CEntity<T> : CChainElement<T> where T : CChainElement<T> { ... }

public class CItem : CEntity<CItem> { ... }

然后这将按照您想要的方式工作:

var allItems = new CChainList<CItem> { new CItem(), new CItem() };

// Both of these are now of type Item.
var firstItem = allItems.m_First;
var secondItem = firstItem.m_Next;

另一种选择是制作ChainElement一个通用接口:

public interface IChainElement<T> where T : IChainElement<T>
{
    T Previous { get; set; }
    T Next { get; set; }
}

但是,您必须明确地将属性添加到要放入列表中的每个类:

public class Entity { }

public class Item : Entity, IChainElement<Item>
{
    public Item Previous { get; set; }
    public Item Next { get; set; }
}

无论哪种方式,您最终都需要修改列表中要使用的所有类。


顺便说一句,您可能希望使用一组更好的命名约定。C用, 命名参数和局部变量以及以InitialCapitals开头的公共字段作为所有类名的前缀m_会使您的代码很难阅读!我会推荐这样的东西:

public class ChainElement<T> where T : ChainElement<T>
{
    public T Previous { get; set; }
    public T Next { get; set; }
}

public class ChainList<T> : IEnumerable where T : ChainElement<T>
{
    public T First { get; private set; }

    public void Add(T element)
    {
        if (First != null)
            First.Previous = element;

        element.Next = First;
        First = element;
    }

    public IEnumerator GetEnumerator() { throw new NotImplementedException(); }
}

public class Entity<T> : ChainElement<T> where T : ChainElement<T> { }

public class Item : Entity<Item> { }
于 2012-09-25T07:53:17.650 回答