重写一个泛型类型方法时出现编译错误

6

我在程序集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

然而编译器现在警告上面一行...

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

这篇答案指出我的解决方案应该可以工作。我想避免使用反射来公开这个方法。它应该是如此简单!

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

3个回答

5
错误信息似乎是误导性的。
请注意,您用公共重写覆盖了一个受保护的虚方法。这不会起作用。将覆盖保护起来,代码应该可以很好地编译...
(我不确定看似错误的错误消息是故障还是编译器特定行为背后有合理的解释)。

啊哈!我知道我是个白痴,我只需要有人指出我的脸水平就行了。所以,如果我想公开暴露它,我需要创建一个新的公共方法并调用A.ReferenceService。谢谢,elgonzo。 - AdamStone
@AdamStone,鉴于Douglas已经解释了错误信息,我认为他的答案应该被标记,而不是我的。 :) - user2819245
@AdamStone:不要啊啊啊啊!;-) - user2819245

5
问题并不完全是由于泛型引起的。问题的原因在于基类方法是protected,而派生类方法是public。因此,重写声明不能更改虚方法的可访问性。重写方法和虚方法必须具有相同的访问级别修饰符。因此,编译器假定这两个方法是不同的,并且派生方法未能从基本方法继承where T:ServiceBase泛型约束。由于派生方法对T一无所知,当您尝试将其传递给基本方法时,它会合理地抱怨T无法转换为ServiceBase

看到我的评论,在elgonzo的帖子下面。谢谢,道格拉斯。我想知道为什么编译器误导了我 :-P - AdamStone
啊,你关于编译器为什么发出错误信息的解释很有道理。这归结于编译器进行检查的顺序以及它首先失败的位置... - user2819245

1

这是因为公共访问修饰符(public)被改为保护访问修饰符(protected)。这可以顺利编译。

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

1
我讨厌解决方案最终与你认为的问题无关。而这几乎总是发生。因此,我讨厌问题。 - AdamStone

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接