简体   繁体   English

通用类型约束不适用

[英]Generic type constraint not applying

I'm writing an emulator and I came across an interesting error: 我在写一个模拟器,但遇到一个有趣的错误:

error CS0311: The type 'T' cannot be used as type parameter 'T' in the generic type or method 'Emulator.Emulator<T>' . 错误CS0311:类型'T'不能用作通用类型或方法'Emulator.Emulator<T>'中的类型参数'T 'Emulator.Emulator<T>' There is no implicit reference conversion from 'T' to 'Emulator.Emulator<T>.EmulatorState' . 从'T'到'Emulator.Emulator<T>.EmulatorState'没有隐式引用转换。

The error is on the following code (specifically the T at Emulator.IOpcode): 错误出现在以下代码上(特别是Emulator.IOpcode上的T):

protected abstract class Chip8Opcode<T> : Emulator<T>.IOpcode where T : Chip8.Chip8State

The simplified code is below ( ideone ): 简化的代码如下( ideone ):

public abstract class Emulator<T> where T : Emulator<T>.EmulatorState
{
    public abstract class EmulatorState { }
    public interface IOpcode
    {
        bool IsValid(T state);
        void Execute(T state);
    }
}

public class Chip8 : Emulator<Chip8.Chip8State>
{
    public class Chip8State : EmulatorState { }
}

abstract class Chip8Opcode<T> : Emulator<T>.IOpcode where T : Chip8.Chip8State
{
}

To my understanding the T should be limited to Chip8State, which can be converted to EmulatorState (which is what Emulator<> requires), however it seems that the generic type constraint isn't applying to the T in Emulator<T> , as the error is "The type 'T'" and not "The type 'Chip8State'." 据我了解的T应当限于Chip8State,它可以转化为EmulatorState(这是模拟器<>要求),但它似乎泛型类型约束不适用于TEmulator<T>作为错误是“类型'T'”而不是“类型'Chip8State'”。 Is this a bug in the compilation or is there a better way to apply type constraints to inherited generics? 这是编译中的错误,还是有更好的方法将类型约束应用于继承的泛型?

Note: This is not a duplicate to similar questions about type collisions, since T is never seen as the constrained type. 注意:这与有关类型冲突的类似问题不是重复的,因为从不将T视为约束类型。

Also: Generics are in place to allow easy extending of the emulator if needed later, although it would be nice to know if there is a better way to do it. 另外:通用方法可以使仿真器在以后需要时轻松扩展,尽管很高兴知道是否有更好的方法可以这样做。

Another way to solve the issue that I used was to create an interface for each class and have them implement it, which allowed covariance and contravariance to be applied correctly in later classes. 解决我使用的问题的另一种方法是为每个类创建一个接口,并让他们实现该接口,从而可以在以后的类中正确应用协方差和逆方差。

interface IEmulator<out T> where T : IEmulatorState
{ ... }
public interface IEmulatorState
{ ... }

which allows: 这使得:

public abstract class Emulator<T> : IEmulator<T> where T : IEmulatorState
{ ... }

public interface IOpcode<in T> where T : IEmulatorState
{ ... }

and most importantly 最重要的是

abstract partial class Chip8Opcode<T> : IOpcode<T> where T : Chip8<T>.Chip8State
{ ... }

Can't you just put it like: 你不能像这样说吗?

abstract class Chip8Opcode<T> : Emulator<Chip8.Chip8State>.IOpcode
    where T : Chip8.Chip8State

Also, check that subject about "covariance and contravariance in generics". 另外,请检查有关“泛型的协方差和自变量”的主题。 It is only possible with interfaces in C#, to some extent. 在某种程度上,只能使用C#中的接口。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM