1

已编辑:重构示例代码以包含一组更相关的对象。

我有一个有趣的情况,我很难找到解决方案。我有一个带有使用泛型的抽象函数的抽象类(请参见下面的示例代码)。在继承类中,我试图重载函数,但我得到了

错误 CS0030:无法将类型“Sample.Thingy”转换为“T”(CS0030)

当然,这不是我的真实代码,但这段代码产生的结果与我得到的结果相同。如果我尝试将返回值转换为 (T),我会收到类似的错误。如果我尝试添加where T : BaseThingyor where T : Thingy,那么我会得到

错误 CS0460:“Sample.Container.GetThingy(Guid)”:无法为覆盖和显式接口实现方法指定约束 (CS0460)

namespace Sample {
    // The abstract base class for thingies
    public abstract class BaseThingy {
        private Guid m_ID;
        private String m_Name;

        public BaseThingy( ) {
            m_ID = Guid.NewGuid( );
        }

        public BaseThingy( Guid id ) {
            m_ID = id;
        }

        public Guid ID {
            get {
                return m_ID;
            }
        }

        public String Name {
            get {
                return m_Name;
            }
            set {
                m_Name = value;
            }
        }
    }

    // The abstract base class for containers
    public abstract class BaseContainer {
        public abstract T GetThingy<T>(Guid id) where T : BaseThingy;
    }

    // Inherits from BaseThingy
    public class RedThingy : BaseThingy {
        private DateTime m_Created;

        public RedThingy( ) : base( ) {
            m_Created = DateTime.Now;
        }

        public RedThingy( Guid id ) : base( id ) {
            m_Created = DateTime.Now;
        }

        public DateTime Created {
            get {
                return m_Created;
            }
        }
    }

    // Inherits from BaseThingy
    public class BlueThingy : BaseThingy {
        public BlueThingy( ) : base( ) {
        }

        public BlueThingy( Guid id ) : base( id ) {
        }
    }

    // Inherits from BaseContainer
    public class Container : BaseContainer {
        private System.Collections.Generic.Dictionary<Guid, RedThingy> m_RedThingies;
        private System.Collections.Generic.Dictionary<Guid, BlueThingy> m_BlueThingies;

        public Container( ) {
            m_Thingies = new System.Collections.Generic.Dictionary<Guid, BaseThingy>();
        }

        public override T GetThingy<T>( Guid id ) where T : BaseThingy {
            if( typeof( T ) == typeof( RedThingy ) {
                if( m_RedThingies.ContainsKey( id ) ) {
                    return m_RedThingies[ id ];
                } else {
                    return null;
                }
            } else if( typeof( T ) == typeof( BlueThingy ) ) {
                if( m_BlueThingies.ContainsKey( id ) ) {
                    return m_BlueThingies[ id ];
                } else {
                    return null;
                }
            } else {
                return null;
            }
        }

        public void AddThing( RedThingy item ) {
            if( item != null && !m_RedThingies.ContainsKey( item.ID ) ) {
                m_RedThingies.Add( item.ID, item );
            }
        }

        public void AddThing( BlueThingy item ) {
            if( item != null && !m_BlueThingies.ContainsKey( item.ID ) ) {
                m_BlueThingies.Add( item.ID, item );
            }
        }
    }
}
4

3 回答 3

2

答案是您传递的类型必须继承自,BaseThingy但这并不意味着您可以Thingy对其进行强制转换。让我举一个例子来简化它:

abstract class BaseThingy
{
}

class Thingy1 : BaseThingy
{
    public void DoSomething()
    {
    }
}

class Thingy2 : BaseThingy
{
    public void DoSomethingElse()
    {
    }
}

class Foo
{
    static T GetItem<T>() where T : BaseThingy
    {
        //Won't compile, Thingy1, while deriving from BaseThingy
        //Could not be the same type of T, derive from it or have
        //An implicit cast operator to T.
        return new Thingy1();
    }

    static void Bar()
    {
        var result = GetItem<Thingy2>();
        //But your method is returning a Thingy1,
        //which doesn't have the following method
        result.DoSomethingElse();
    }
}

Bar()将期望result是类型Thingy2,但GetItem正试图返回一个Thingy1.

于 2013-01-06T06:17:31.490 回答
1

问题是,由于您已经在基类中设置了约束,您不需要在派生类中再次指定它们。这就是它给出该错误的原因。

除了它产生这个错误,我不明白你有什么问题。只是不要在继承的类中指定约束。

为了解决转换问题,您必须对其进行转换:

public T Get<T>() where T : Thingy
{
    RedThingy thingy = GetRedThingy();
    return (T)thingy;
}

如果编译器不允许您这样做(我现在没有打开 Visual Studio),您可以先将其转换为 object,然后再转换为 T(这是一种解决方法)。

public T Get<T>() where T : Thingy
{
    RedThingy thingy = GetRedThingy();
    return (T)((object)thingy);
}

希望能帮助到你。

于 2013-01-06T06:22:59.967 回答
0

最快的解决方法是将基本实现约束更改为 Thingy 而不是 BaseThingy。如果这对您的应用程序没有意义,那么您很可能只是没有使用最佳设计模式来解决您的问题。在后一种情况下,如果可以在高层次上对您的问题进行更多解释,那么我相信我们可以为您提供一些其他关于如何解决问题的建议。

于 2013-01-06T06:29:12.950 回答