2012-07-22 114 views
2

我有子弹:泛型协方差变通办法?

public LaserBullets : Projectile 

我有枪,从与与派生枪响子弹型基武器继承:

public LaserWeapon : Weapon<LaserBullets> 

我必须建立在当前武器属性玩家的:

public Weapon<Projectile> CurrentWeapon 
{ 
    set { currentWeapon = value; } 
} 

这失败(不能隐式转换LaserWeaponWeapon<Projectile>

player.CurrentWeapon = new LaserWeapon(); 

我读过关于不支持C#中的某些协方差,但我不想认为我卡在这里。有什么方法可以让我的情况发挥作用吗?我试图在玩家类中保持基础武器,但在另一个类中使用更具体的武器。

我试着为LaserWeapon创建自己的投射操作符,但是我得到了无法投射到基类的错误。

+0

我以为这会奏效,但我会承认你没说的。如果你制作武器的'Weapon'基础类是什么?然后让'CurrentWeapon'只是一个'Weapon'? – 2012-07-22 22:44:38

+0

我会看到它的。但是这可能是个问题,因为武器有一个抽象方法Fire()返回TProjectile。 'Player'在基类上调用这个方法。这导致另一种类型的协方差问题,其中指定基本返回类型并用派生返回类型重写也具有编译时问题。 – 2012-07-22 22:55:34

+0

我相信@JonathonReinhart是正确的 - 根据我的经验,在这种情况下,我总是使用非泛型基类或接口。 – 2012-07-22 22:56:24

回答

5

我相信,如果Weapon<T>被宣布像这样一个协接口你的例子会工作:

public interface Weapon<out TProjectile> 
{ 
} 

这只会在哪里工作TProjectile被用作返回值,例如:

TProjectile Fire(); 

但将不是工作,其中TProjectile被用作输入参数,例如:

LoadClip(IEnumerable<TProjectile> ammo); 

从您的意见,我可以看到你的一般返回值后的时候,所以要的界面如下:

public interface IWeapon<out TProjectile> where TProjectile : Projectile 
{ 
    TProjectile Fire(); 
} 

然后使用这个接口的实现;没有什么能阻止你拥有一个有用的基类,例如

public abstract class Weapon<TProjectile> : IWeapon<TProjectile> where TProjectile : Projectile 
{ 
    public abstract TProjectile Fire(); 
} 

只要您的播放器类是沿着线:

public class Player 
{ 
    public IWeapon<Projectile> CurrentWeapon { get; set; } 
} 

这允许你仍然使用CurrentWeapon.Fire()将返回的Projectile一个实例。

+0

非常感谢。我从你的回复中了解了很多,它似乎适用于我的特定场景。 – 2012-07-23 01:20:37

1

制作Weapon<T>继承的非泛型类Weapon。在代码中使用该类而不是Weapon<Projectile>