覆盖泛型类型方法时的编译错误

时间:2014-01-12 14:49:23

标签: c# .net generics inheritance

我在程序集A中公开了以下类:

public abstract class ServiceDependencyHost
{
    protected virtual T ReferenceService<T>() where T : ServiceBase
    {
        // Virtual implementation here...
    }
}

我将这个派生类暴露在一个单独的程序集中(B):

public sealed class ProcessServiceOperation : ServiceDependencyHost
{
    public override T ReferenceService<T>()
    {
        // Override implementation here...

        return base.ReferenceService<T>();
    }
}

使用上面显示的代码,编译器在这一行上抱怨:

return base.ReferenceService<T>();

类型'T'不能在泛型类型或方法A.ReferenceService()中用作类型参数'T'。从'T'到'System.ServiceProcess.ServiceBase'没有装箱转换或类型参数转换。

当然,我尝试复制程序集B中的约束:

public override T ReferenceService<T>() where T : ServiceBase

但是编译器现在警告上面的那行...

覆盖和显式接口实现方法的约束是从base方法继承的,因此不能直接指定它们。

This answer表示我的解决方案应该有效。我想避免使用反射公开公开此方法。应该这么简单!

提前感谢任何能够发现我犯了什么错误的人。

3 个答案:

答案 0 :(得分:4)

错误消息似乎具有误导性。

请注意,您使用公开覆盖覆盖了受保护的虚拟方法。那不行。使覆盖也受到保护,代码应该编译得很好......

(我不确定看似错误的错误消息是否是一个小问题,或者编译器的这种特殊行为背后是否有合理的解释。)

答案 1 :(得分:4)

问题并非严格归因于仿制药。问题的原因是基类方法是protected,而派生类方法是public

  

覆盖声明无法更改虚拟方法的可访问性。覆盖方法和虚方法都必须具有相同的访问级别修饰符。

因此,编译器假定这两个方法是不同的,并且派生方法无法从基本方法继承where T : ServiceBase泛型约束。由于派生方法对T一无所知,因此当您尝试将T传递给基本方法时,它会抱怨ServiceBase无法转换为{{1}}。

答案 2 :(得分:1)

因为公共=&gt;保护。编译好

public abstract class ServiceDependencyHost
        {
            protected virtual T ReferenceService<T>() where T : new()
            {
                return new T();
            }
        }

        public sealed class ProcessServiceOperation : ServiceDependencyHost
        {
            protected override T ReferenceService<T>()
            {
                // Override implementation here...

                return base.ReferenceService<T>();
            }
        }