C#内部接口与内部实现

时间:2011-05-24 21:52:58

标签: c# interface internal

我发现了一些我不太懂的东西。

我有一个项目,我有一个内部接口。实现该接口的类也是内部的。在接口的实现中,我制作了我实现的所有成员,内部。我没有做过明确的实施。

我有两个接口和两个类来实现这些工作正常的接口。

它看起来像这样:

internal interface IA
{
    void X();
}

然后

internal class CA : IA
{
    internal void X()
    {
        ...
    }
}

这适用于前面提到的两个课程。但是当我尝试用另一个接口和类做它时,它不起作用。事实上,对于上面的例子,我得到错误:

'WindowsFormsApplication1.CA'未实现接口成员'WindowsFormsApplication1.IA.X()'。 'WindowsFormsApplication1.CA.X()'无法实现接口成员,因为它不是公共的。

我意识到我可以将这些方法设为公开或者做一个显式的实现(并省略内部和公共修饰符),但我只是为什么它适用于它使用的两个类,但我似乎是无法在其他任何地方复制它。

稍微屠宰一下代码(因为它是保密的),这是我项目中实际工作的代码之一。

internal interface IScanner
{
    void SetHardware(Hardware hardware);
    void Start();
    void PauseScan();
    void ResumeScan();
    void Stop();
    bool InScan { get; }
    event ScanCompleteHandler ScanComplete;
}

然后我上课了:

internal class MyScanner : IScanner
{
    internal void SetHardware(Hardware hardware)
    {
       ...
    }

    internal void Start()
    {
        ...
    }

    internal void Stop()
    {
        ...
    }

    internal void PauseScan()
    {
        ...
    }

    internal void ResumeScan()
    {
        ...
    }

    internal bool InScan
    {
        get
        {
            ...
        }
    }

    internal event ScanCompleteHandler ScanComplete;
}

为了让事情更奇怪,我创建了另一个名为Temp的内部类。然后我让它实现了IScanner接口,我将MyScanner的实现复制并粘贴到它上面,它不会编译,给我一个错误:“无法实现接口成员,因为它不公开。”

有人可以解释这种不一致吗?

由于

(更新以修正拼写错误并澄清一些文字)

编辑:其他信息

我通过反射器运行代码,我的实现已被编译为显式实现,即使它们不是显式的。反射器没有显示内部关键字的迹象。我可以猜到的是,这是编译器中的某种故障,由于某种原因,它允许我使它们内部和隐式,并且它以某种方式解决了它作为一个显式实现。

我多次查看代码。我找不到任何其他解释。

6 个答案:

答案 0 :(得分:19)

如果您隐式实现接口,我认为该成员必须声明为public。在您的示例中,CA尝试隐式实现X()方法,但未声明为公共方法。如果您想将X()保留为内部,那么您应该使用显式接口实现。

void IA.X() { /* stuff */ }

但是,我还要补充一点,将X()方法公开不会造成任何伤害,因为类是内部的,因此该成员已经受到该访问修饰符的限制......也就是说,它已经是有效的内部...所以你不妨把它公之于众!

答案 1 :(得分:3)

我知道问题已经有一段时间了,但也许我可以对此有所了解。根据发现here的C#语言规范,您描述的行为应该是不可能的。因为在20.4.2接口映射下,可以说实现是显式的或映射到公共非静态成员。所以要么你有其他场景而不是你在这里描述的场景,要么你在编译器中发现了一个错误:)。

答案 2 :(得分:2)

可能你的“Temp”类是公开的,而IScanner是内部的。这就是您收到此错误的原因。我认为这非常烦人,因为你被迫明确地实现它,你不能将它们指定为抽象或虚拟。对于虚拟内容,我被迫执行相同API的隐式内部虚拟实现,然后从显式版本调用隐式版本。难看。

答案 3 :(得分:2)

在Interface声明中有一个内部修饰符是可以的,但是你不能在界面中有任何修饰符,换句话说,你不能有任何接口成员的修饰符。就这么简单!

示例:

internal interface IA
{
    void X(); //OK. It will work
}


internal class CA : IA
{
    **internal** void X() // internal modifier is NOT allowed on any Interface members. It doesn't compile. If it works in your project it's because either you DON'T have the void X() method in the Interface or your are inheriting from a wrong interface maybe accidentally 
    {
        ...
    }
}

接口声明可以声明零个或多个成员。接口的成员必须是方法,属性,事件或索引器。接口不能包含常量,字段,运算符,实例构造函数,析构函数或类型,接口也不能包含任何类型的静态成员。 所有接口成员都隐式具有公共访问权限。接口成员声明包含任何修饰符是编译时错误。特别是,不能使用abstract,public,protected,internal,private,virtual,override或static修饰符声明接口成员。

参考: https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/interfaces

答案 4 :(得分:0)

据我所知,您无法实现接口方法internal。如你所说,你可以明确地实现它们,但是有人仍然可以((IScanner)myScanner).SetHardware(hw)

您是否100%确定您的MyScanner实施不会执行以下操作:

internal class MyScanner : IScanner
{
    void IScanner.SetHardware(Hardware hardware) { this.SetHardware(hardware); }
    internal void SetHardware(Hardware hardware)
    {
      ...
    }
    ....
}

或者这个:

internal partial class MyScanner : IScanner
{
    internal void SetHardware(Hardware hardware)
    {
        ...
    }
}

internal partial class MyScanner
{
    void IScanner.SetHardware(Hardware hardware)
    {
        this.SetHardware(hardware);
    }
}

答案 5 :(得分:0)

如果您打算从外部隐藏某个实现,则可以像下面这样显式实现它:

internal class LDialogService : ILDialogService, ILDialogInternalService
{

    public async Task<TValue> ShowAsync<TValue>(ILDialogFragment fragment)
    {
        throw new NotImplementedException();
    }

    void ILDialogInternalService.SetComponent(LDialog component)
    {
        throw new NotImplementedException();
    }
}

在上面的代码中,我想将ShowAsync方法暴露给外部,但将SetComponent保留在内部。由于ILDialogInternalServiceinternal,因此只有通过反射才能从外部调用它。