C#中更复杂的扩展泛型

问题描述 投票:2回答:2

我有两类具有泛型的树,我一无所知,我知道如何用<? extends ...>在Java中解决。

第一棵AI树:

abstract class AbstractAI<TCtrl> : MonoBehaviour where TCtrl: IRotableWeaponController

abstract class AbstractShipAI : AbstractAI<IShipController>

class ModularAI : AbstractShipAI

Some other classes that extend AbstractAI and use various modules

模块树:

abstract class AbstractModule<TAi, TCtrl> : AIModule where TAi: AbstractAI<TCtrl> where TCtrl: IRotableWeaponController
{
    public virtual void Init(TAi parent)
}

class ShootModule: AbstractModule<AbstractAI<IRotableWeaponController>, IRotableWeaponController>

Some other modules that extend AbstractModule and can be used only with some AIs, that have required capabilities

使用的控制器接口树:

interface IRotableWeaponController

interface IShipController: IRotableWeaponController

Other interfaces extending IRotableWeaponController...

问题是:

class ModularAI : AbstractShipAI
{
    public ShootModule shootModule;

    protected override void Start()
    {
        shootModule.Init(this); // Error: Argument type 'ModularAI' is not assignable to parameter type 'AbstractAI<IRotableWeaponController>'    
    }
}

[ModularAIAbstractAI<IShipController>IShipControllerIRotableWeaponController,但出现错误。

在Java中,我会这样做:

abstract class AbstractModule<TAi, TCtrl> : AIModule where TAi: AbstractAI<? extends TCtrl> where TCtrl: IRotableWeaponController

我知道它有点复杂,可能有一种更好的方法来设计它(而且我可能最终有一天会付诸实践),但是我想知道如何解决这个问题。拜托,我该怎么做?

c# generics
2个回答
3
投票
class Fruit { } class Apple : Fruit { } class FruitMaker<T> where T : Fruit { } class Program { static void HandleFruit(FruitMaker<Fruit> fruitMaker) { } static void Main() { FruitMaker<Apple> appelMaker = new FruitMaker<Apple>(); FruitMaker<Fruit> fruitMaker = appelMaker; //cannot convert from 'FruitMaker<Apple>' to 'FruitMaker<Fruit>' HandleFruit(fruitMaker); } }

您需要的是泛型协方差,您需要将FruitMaker<Apple>传递给期望FruitMaker<Fruit>的方法。这可以通过out关键字启用,您想要的是class FruitMaker<out T> where T : Fruit { },但是您不能这样做,因为FruitMaker不是接口。您可以按以下方式解决此问题:

class Fruit { }
class Apple : Fruit { }
interface IFruitMaker<out T> where T : Fruit { }
class FruitMaker<T> : IFruitMaker<T> where T : Fruit { }

class Program
{
    static void HandleFruit(IFruitMaker<Fruit> fruitMaker) { }

    static void Main()
    {
        FruitMaker<Apple> appelMaker = new FruitMaker<Apple>();
        IFruitMaker<Fruit> fruitMaker = appelMaker; //this is allowed thanks to the out keyword
        HandleFruit(fruitMaker);

    }
}

注意,我引入一个界面只是为了添加out键盘。


0
投票
interface IAbstractAI<out TCtrl> where TCtrl : IRotableWeaponController { } abstract class AbstractAI<TCtrl> : MonoBehaviour, IAbstractAI<TCtrl> where TCtrl : IRotableWeaponController { } abstract class AbstractModule<TAi, TCtrl> : AIModule where TAi : IAbstractAI<TCtrl> where TCtrl : IRotableWeaponController { public virtual void Init(TAi parent) { } } class ShootModule : AbstractModule<IAbstractAI<IRotableWeaponController>, IRotableWeaponController> { } class ModularAI : AbstractShipAI { public ShootModule shootModule; protected override void Start() { shootModule.Init(this); // Error: Argument type 'ModularAI' is not assignable to parameter type 'AbstractAI<IRotableWeaponController>' } }
© www.soinside.com 2019 - 2024. All rights reserved.