如何在c#中基类是通用的时将子类强制转换为基类

时间:2015-12-13 11:56:33

标签: c# generics casting

我有这些课程:

public class BaseGame<T> where T : BaseQuestion
{
    //some fileds and methods
}

public class BaseQuestion 
{
    //some fileds and methods
}

public class Question : BaseQuestion
{
    //some fileds and methods
}

public class SampleGame : BaseGame<Question>
{
    //some fileds and methods
}

每当我想将BaseGame转换为SampleGame时,我都会收到错误。

void SetValue(BaseGame<BaseQuestion> _game)
{
    SampleGame = (SampleGame) _game;
}

无法将BaseGame类型隐式转换为SampleGame。 如何解决这个问题?

感谢。

1 个答案:

答案 0 :(得分:0)

将您的代码更改为:

public interface IBaseGame<out T> where T : BaseQuestion
{
}

public class BaseGame<T> : IBaseGame<T>
    where T : BaseQuestion
{
}

public class BaseQuestion 
{
}

public class Question : BaseQuestion
{
}

public class SampleGame : BaseGame<Question>
{
}

然后你的方法:

void SetValue(IBaseGame<BaseQuestion> _game)
{
    var SampleGame = (SampleGame) _game;
}

为什么你的代码被破坏了?

你无法进行演员表,因为BaseGame不是协变的。这意味着编译无法保证演员阵容是安全的。例如,以下示例:

public class BaseGame<T> where T : BaseQuestion
{
    private List<T> Questions { get; set; }
    public void AddQuestion(T question) { Questions.Add(question); }
}

var game = new BaseGame<Question> { Questions = new List<Question> };
game.AddQuestion(new Question());

好的,现在你的游戏有一个Question列表,其中有一个问题。现在让我们投吧:

public class BrokenQuestion : BaseQuestion
{
} 

public class BrokenGame : BaseGame<BrokenQuestion>
{
}

var brokenGame = (BrokenGame)game;
brokenGame.Add(new BrokenQuestion());`

糟糕!我们刚刚向BrokenQuestion添加了List<Question>。不好。

将模板参数定义为out T而不是T意味着我们正在签订一份我们不会接受 T子类的合同,但我们可以返回他们。这意味着它现在非法公开AddQuestion(T question)。现在,编译器可以确保永远不会向BrokenQuestion添加List<Question>

有关详细信息,请see here