【问题标题】:Interface implementation fails for generic type, because of "does not have the matching return type" error泛型类型的接口实现失败,因为“没有匹配的返回类型”错误
【发布时间】:2015-08-28 21:56:33
【问题描述】:

我有一堂课:

 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; } }

}

还有一个界面:

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

代码编译失败,提示信息

错误 28“Server.Models.Structures.Structure”未实现接口成员“Server.Models.Structures.IStructure.Stats”。 “Server.Models.Structures.Structure.Stats”无法实现“Server.Models.Structures.IStructure.Stats”,因为它没有“Server.Models.Structures.StructureStats”的匹配返回类型。 C:\SRDevGit\freecon-galactic-server\SRServer\Server.Models\Structures\Structure.cs

我不确定问题是什么; Structure.Stats {get;} 的返回类型应保证与接口定义匹配,因为泛型类型 S 被定义为从 StructureStats 派生的

where S:StructureStats, new()

我错过了什么?如果可能的话,我想避免使 IStructure 通用化,因为它会使

的集合复杂化
<IStructure<GenericType>>

因为 GenericType 是一个多态类。

【问题讨论】:

  • C# 不支持返回类型差异。
  • 你真正想要达到什么目的?这种方法似乎充其量是令人费解的。
  • 我试图避免强制转换。 Structure、StructureModel 和 StructureStats 都是多态类,但是它们受到约束,因此特定的派生结构必须与特定的派生 StructureModel 和特定的派生 StructureStats 一起使用。主要困难在于选择将对象数据分离到自己的类(StructureModel)中,类似于 MVVM 模式。

标签: c# generics interface


【解决方案1】:

C# 是强类型的, 不支持协变返回类型,因此要从 IStructure 继承,Structure 必须返回确切的签名StructureStats Stats{ get; set;}。像StructureStatsDerived Stats{ get; set;} 这样的东西不是完全匹配的,编译器会拒绝它。

看起来您实际上并不需要通用参数 S。您可以删除 S 并返回 StructureStats。

【讨论】:

  • 注意:C# 是强类型的这一事实在这里并不重要(可以支持强类型语言中的返回值变化)...这是 C# 选择要求完全匹配的事实,如剩下的答案。
  • @Alexei 我同意,要求精确签名匹配继承层次结构并不是强类型语言的先决条件,但是这个规则在强类型语言中比在弱类型语言中更合乎逻辑打字语言。这就是为什么我认为它值得一提。不过,好点。我把“所以”改成了“和”。
  • 我明白了。根据 PetSerAl 的评论,快速搜索将我带到维基百科页面 en.wikipedia.org/wiki/Covariant_return_type,这表明这是 C# 固有的设计选择。我已经编辑了答案以包含术语。非常感谢。
  • 出于好奇,谁能详细说明为什么 C# 不支持协变返回类型?
【解决方案2】:

不使用泛型接口是无法实现的,还需要为Structure&lt;T, S&gt;切换泛型约束中的顺序

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; }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-10-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多