通用协方差解决方法?

时间:2012-07-22 22:40:03

标签: c# generics casting

我有子弹:

public LaserBullets : Projectile

我有一把枪,它继承了一种基本武器,其子弹类型与衍生枪一起使用:

public LaserWeapon : Weapon<LaserBullets>

我有一个属性来建立玩家的当前武器:

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

此操作失败(无法隐式投射LaserWeaponWeapon<Projectile>

player.CurrentWeapon = new LaserWeapon();

我读过关于C#中某些协方差的支持,但我不想认为我被困在这里。有没有办法让我的情况有效?我正在尝试在玩家类中维护一个基础武器,但是在另一个类中使用更具体的武器。

我尝试为LaserWeapon创建自己的强制转换操作符,但是我收到了一个关于无法强制转换为基类的错误。

2 个答案:

答案 0 :(得分:5)

我相信如果Weapon<T>是一个如此声明的协变接口,那么你的例子就会有效:

public interface Weapon<out TProjectile>
{
}

这仅适用于将TProjectile用作返回值的情况,例如:

TProjectile Fire();

NOT 会将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的实例。

答案 1 :(得分:1)

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