声明Generic类型必须实现Generic Constraint

时间:2018-02-21 11:53:38

标签: c# generics

我希望Foo<T>要求任何实例化都自己实现T。 (Foo<>可以是抽象的,也可以是接口)

或者如果它实际上是MyFoo : IFoo<ConcreteClass>,那么MyFoo : ConcreteClass

目前我已经通过让Foo<T>声明类型为T的属性来实现我的基本目标,通常通过返回类本身来满足,但我很好奇我是否可以更直接地执行它。

<小时/> 编辑:我确信自己这是不可能的。 作为参考,有问题的代码如下所示:

public abstract class BotController<TBot> : BotController, IBotController<TBot>
{
    protected BotController(TBot wrappedBot, PlayerRecord player, long timeout) : base(player, timeout)
    {
        WrappedBot = wrappedBot;
    }

    protected TBot WrappedBot { get; set; }
    public abstract TBot ControlledBot { get; }

    private string cachedName;
    public  override string BotName => (cachedName = (cachedName ?? WrappedBot.Name));

    protected T SafelyPerformBotActionWithTimer<T>(Func<TBot, T> botAction, string errorDescriptor)
    {
        return SafelyPerformBotActionWithTimer(() => botAction(WrappedBot), errorDescriptor);
    }

    protected void SafelyPerformBotActionWithTimer(Action<TBot> botAction, string errorDescriptor)
    {
        SafelyPerformBotActionWithTimer(() => botAction(WrappedBot), errorDescriptor);
    }
}


public class BattleshipsController : BotController<IBattleshipsBot>, IBattleshipsBot
{
    public BattleshipsController(IBattleshipsBot battleshipImplementation, PlayerRecord playerRecord, long timeout = 1000)
        : base(battleshipImplementation, playerRecord, timeout) {}

    public override IBattleshipsBot ControlledBot => this;


    public IEnumerable<IShipPosition> GetShipPositions()
    {
        //qqMDM validate Ship Positions here?
        return SafelyPerformBotActionWithTimer(b => b.GetShipPositions(), "specifying ship positions");
    }

    public IGridSquare SelectTarget()
    {
        var target = SafelyPerformBotActionWithTimer(b => b.SelectTarget(), "selecting a target");

        if (target.IsOutsideGrid())
        {
            throw new ShotOffBoardException($"{BotName} has tried to shoot off the board, aiming at square {target.Row}{target.Column}", this);
        }
        return target;
    }

    public void HandleShotResult(IGridSquare square, bool wasHit)
    {
        SafelyPerformBotActionWithTimer(b => b.HandleShotResult(square, wasHit), "handling shot result");
    }

    public void HandleOpponentsShot(IGridSquare square)
    {
        SafelyPerformBotActionWithTimer(b => b.HandleOpponentsShot(square), "handling opponent's shot");
    }

    public string Name => BotName;
}

3 个答案:

答案 0 :(得分:0)

我想象的具体事情是不可能的。

我想要一些语法:

abstract class Foo<TWrappedType> where Foo : TWrappedType

如果TWrappedType是一个接口(它将在我的情况下),它在概念上可行,但如果TWrappedType是一个具体类,则可能永远不会工作,因为C#不进行多重继承。

由于您无法约束Generic Type是接口还是类,因此语法不存在。

当我写这个问题时,我已经走了一半,因此这个问题很混乱,但还不足以证明这是不可能的。

答案 1 :(得分:0)

如果我理解正确,您可以使用中间类/接口执行此操作:

interface IInterface<T>
{ }

class Foo<T> : IInterface<T> where T : IInterface<T>
{
}

但你的问题并不是那么清楚。我不确定这是否与你想要的类似,这种类声明只会让我头疼。

答案 2 :(得分:-1)

为了考虑到这一点的未来人们的利益,最初似乎可以获得一些好处,并在端点处使用相同的语法(Foo<T>看起来像T),通过设置显式和隐式转换运算符,只需返回抽象类的property

然而,语言中不允许这样做。

见这里:implicit operator using interfaces