Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/318.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 通用协方差变通方法?_C#_Generics_Casting - Fatal编程技术网

C# 通用协方差变通方法?

C# 通用协方差变通方法?,c#,generics,casting,C#,Generics,Casting,我有子弹: public LaserBullets : Projectile 我有一把枪,它继承了一把基础武器,子弹类型与派生枪一致: public LaserWeapon : Weapon<LaserBullets> 我读过关于C#中不支持某些协方差的文章,但我不想认为我被困在这里了。有什么办法使我的处境有效吗?我试图在玩家职业中保留一件基本武器,但在另一个职业中使用更具体的武器 我尝试为LaserWeapon创建自己的强制转换操作符,但我遇到了一个错误,即无法向基类强制转换或

我有子弹:

public LaserBullets : Projectile
我有一把枪,它继承了一把基础武器,子弹类型与派生枪一致:

public LaserWeapon : Weapon<LaserBullets>
我读过关于C#中不支持某些协方差的文章,但我不想认为我被困在这里了。有什么办法使我的处境有效吗?我试图在玩家职业中保留一件基本武器,但在另一个职业中使用更具体的武器


我尝试为LaserWeapon创建自己的强制转换操作符,但我遇到了一个错误,即无法向基类强制转换或从基类强制转换。

如果
武器
是这样声明的协变接口,我相信您的示例会起作用:

public interface Weapon<out TProjectile>
{
}
但当
t项目
用作输入参数时,将不起作用,例如:

LoadClip(IEnumerable<TProjectile> ammo);
LoadClip(IEnumerable弹药);
从您的评论中,我可以看出您在寻找通用返回值,因此创建如下界面:

public interface IWeapon<out TProjectile> where TProjectile : Projectile
{
    TProjectile Fire();
}
公共接口IWeapon,其中tproject:sparket
{
t射出火焰();
}
然后使用此接口实现;没有什么能阻止你拥有一个有用的基类,例如

public abstract class Weapon<TProjectile> : IWeapon<TProjectile> where TProjectile : Projectile
{
    public abstract TProjectile Fire();
}
公共抽象类武器:IWeapon,其中tproject:sparket
{
公共抽象Tprojectle Fire();
}
只要您的玩家等级符合以下要求:

public class Player
{
    public IWeapon<Projectile> CurrentWeapon { get; set; }
}
公共类播放器
{
公共IWeapon currentWearm{get;set;}
}

这允许您仍然使用
currentWearm.Fire()
,它将返回
投射物的一个实例

生成一个
武器
继承的非泛型类。使用该类,而不是代码中的武器。

我认为这会起作用,但我相信你的话,它不会起作用。如果你制作了一个
武器
基类,它是
武器
的来源,那会怎么样?然后把
currentwearm
做成一件
wearm
?我来看看。但这可能是一个问题,因为
武器
有一个抽象方法
Fire()
,返回
tproject
Player
在基类上调用此方法。这导致了另一种类型的协方差问题,在这种情况下,指定基返回类型并用派生返回类型重写也有编译时问题。我相信@JonathonReinhart是正确的-以我的经验,在这种情况下,我总是使用非泛型基类或接口。@JonathonReinhart这不可能,因为它不是类型安全的。如果允许,您可以将
列表
分配给
列表
类型的变量,然后向字符串列表添加任何内容。非常感谢。我从你的回答中学到了很多,它似乎适用于我的特定场景。
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; }
}