列表<a> = list<b> when B inherits from A possible?</b></a>

时间:2013-07-12 16:41:51

标签: c#

基本上我有

继承自BallisticProjectile类的

Projectile类。现在我可以做到这一点

Projectile A;
BallisticProjectile B;

Projectile myfunction()
{
    return B;
}

并将B作为射弹返回。

但我做不到

list<Projectile> myfunction()
{
    return B;
}

我不知道如何克服这一点。

我是否需要一个包装类,所以我喜欢

ProjectileList
{
    list<projectile> Projectiles;
}

BallisticProjectiles : Projectile
{
    list<ballisticprojectile> Projectiles;
}

真实代码(来自统一游戏引擎)

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
public abstract class Weapon : MonoBehaviour {
    IEnumerable<Projectile> _Projectile;


    public virtual IEnumerable<Projectile> projectile
    {
        get
        {
            return _Projectile;
        }
        set
        {
            _Projectile = value;
        }
    }
}

其他剧本

public override IEnumerable<BallisticProjectile> projectile {
    get {
        if(_BallisticProjectile == null)
            Debug.Log("ERROR: " + this.gameObject.name + " NO PROJECTILE");

        return _BallisticProjectile;
    }
    set {
        if(value is IEnumerable<BallisticProjectile>)
        {
            _BallisticProjectile = value as IEnumerable<BallisticProjectile>;
            base.projectile = _BallisticProjectile;
        }
    }
}

2 个答案:

答案 0 :(得分:1)

在C#4中,如果B从A继承,则可以将IEnumerable<B>转换为IEnumerable<A>。这是可能的,因为IEnumerable<T>与T协变(但List<T>是逆变的T)。所以你可以使用IEnumerable&lt;&gt;而不是列表&lt;&gt;

答案 1 :(得分:0)

List<BallisticProjectile>不能用作List<Projectile>。一种简单的方法可以查看为什么您可以将new Projectile()添加到List<Projectile>,这对于List<BallisticProjectile>没有任何意义。

此方法允许您以通用方式设置射弹类型,并可以解决您的问题(与建议的p.s.w.g相同):

public class ProjectileList<T> where T : Projectile
{
    List<T> Projectiles;
}
在您的情况下

更新,可能如下所示:

public abstract class Weapon<T> : MonoBehaviour where T : Projectile {
    public virtual IList<T> Projectiles { get; set; }
}

然后:

public class Crossbow : Weapon<BallisticProjectile> {
    // if you needed to override the implementation, you'd start with this:
    // public override IList<BallisticProjectile> Projectiles { get { } set { } }
}

这里的问题是,当您覆盖属性时,C#不允许您更改属性(或其他成员)的类型。类型是否以某种方式兼容并不重要,您必须使用相同的类型声明它。通过这种方式,泛型是一种使虚拟属性更改为BallisticProperty的方法。