EDITED:重构示例代码以包含更相关的对象集。
我有一个有趣的情况,我找不到解决方案。我有一个抽象类,其中包含一个使用泛型的抽象函数(参见下面的示例代码)。在继承类中,我试图重载函数,但我得到了
错误CS0030:无法将类型'Sample.Thingy'转换为'T'(CS0030)
当然,这不是我真正的代码,但是这段代码产生的结果与我得到的结果相同。如果我尝试将返回值转换为(T),我会得到类似的错误。如果我尝试添加where T : BaseThingy
或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 );
}
}
}
}
答案 0 :(得分: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
。
答案 1 :(得分: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);
}
希望它有所帮助。
答案 2 :(得分:0)
最快的解决方法是将基本实现约束更改为Thingy而不是BaseThingy。如果这对您的应用程序没有意义,那么很可能您只是没有使用最佳设计模式来解决您的问题。在后一种情况下,如果可以在更高层次上解释一下你的问题,那么我相信我们可以给你一些关于如何处理它的其他建议。