简体   繁体   中英

Interface implementation fails for generic type, because of “does not have the matching return type” error

I have a class:

 public abstract class Structure<T, S> : IStructure
    where T : StructureModel<S>, new()
    where S : StructureStats, new()
{
    protected T _model;

    public S Stats { get { return _model.Stats; } set { _model.Stats = value; } }

}

and an interface:

public interface IStructure
{
    StructureStats Stats{ get; set;}
}

The code fails to compile, with the message

Error 28 'Server.Models.Structures.Structure' does not implement interface member 'Server.Models.Structures.IStructure.Stats'. 'Server.Models.Structures.Structure.Stats' cannot implement 'Server.Models.Structures.IStructure.Stats' because it does not have the matching return type of 'Server.Models.Structures.StructureStats'. C:\\SRDevGit\\freecon-galactic-server\\SRServer\\Server.Models\\Structures\\Structure.cs

I am unsure as to what the problem is; the return type of Structure.Stats {get;} should be guaranteed to match the interface definition, since generic type S is defined as deriving from StructureStats by

where S:StructureStats, new()

What am I missing? I would like to avoid making IStructure generic, if possible, as it would complicate collections of

<IStructure<GenericType>>

because GenericType is a polymorphic class.

C# is strongly typed, and does not support covariant return types, so to inherit from IStructure, Structure has to return the exact signature StructureStats Stats{ get; set;} StructureStats Stats{ get; set;} . Something like StructureStatsDerived Stats{ get; set;} StructureStatsDerived Stats{ get; set;} is not an exact match and the compiler rejects it.

It looks like you don't actually need the generic parameter S. You could drop the S and just return StructureStats.

There's no way to achieve it without use a generic interface, also you need to switch the order in generic constraints for Structure<T, S>

public class Structure< T, S> : IStructure<S>
where S : StructureStats, new()
where T : StructureModel<S>, new()
{
    protected T _model;

    public S Stats { get { return _model.Stats; } set { _model.Stats = value; } }

}

public interface IStructure<S> where S : StructureStats
{
    S Stats { get; set; }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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