C# 内部接口和内部实现

发布于 2024-11-09 16:05:28 字数 1783 浏览 0 评论 0原文

我突然发现了一些我不太明白的事情。

我有一个项目,其中有一个内部界面。实现该接口的类也是内部的。在接口的实现中,我将实现的所有成员设为内部成员。我没有做明确的实现。

我有两个接口和两个类,它们实现了这些接口,并且可以正常工作。

它看起来像这样:

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 的实现复制并粘贴到它上面,但它无法编译,给出错误:“无法实现接口成员,因为它不是公共的。”

谁能解释这种不一致?

谢谢

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

编辑:附加信息

我通过反射器运行代码,我的实现已编译为显式实现,即使它们并不显式。 Reflector 没有显示任何内部关键字的迹象。我所能猜测的是,这是编译器中的某种故障,出于某种原因,它允许我将它们设为内部和隐式,并且它以某种方式将其解决为显式实现。

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

I've struck upon something I don't really understand.

I have a project, where I have an interface that is internal. The class that implements that interface is also internal. In the implementation of the interface, I make all the members that I implement, internal. I did not do an explicit implementation.

I have two interfaces and two classes that implement those interfaces where this works fine.

It would look something like this:

internal interface IA
{
    void X();
}

and then

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

This works fine for the two aforementioned classes. But when I try to do it with another interface and class, it doesn't work. In fact, for the example above, I get the error:

'WindowsFormsApplication1.CA' does not implement interface member 'WindowsFormsApplication1.IA.X()'. 'WindowsFormsApplication1.CA.X()' cannot implement an interface member because it is not public.

I realize I can make the methods public or do an explicit implementation (and omit the internal and public modifiers), but I'm simply confused as to why it works with the two classes it works with and yet I seem to be unable to replicate it anywhere else.

Butchering the code a bit (because it's confidential), this is one of the ones that actually works in my project.

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

Then I have the class:

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

To make things even stranger, I created another internal class called Temp. I then had it implement the IScanner interface and I copied and pasted the implementation from MyScanner over to it and it won't compile, giving me the error that: "cannot implement an interface member because it is not public."

Can anyone explain this inconsistency?

Thanks

(Updated to fix a typo and clarify some text)

EDIT: Additional Information

I ran the code through reflector and my implementations have been compiled as explicit implementations, even though they aren't explicit. Reflector shows no signs of the internal keywords. All I can guess is that this is some sort of glitch in the compiler that, for some reason, allowed me to make them internal and implicit and that it somehow resolved that as being an explicit implementation.

I've looked over the code a number of times. I can't find any other explanation for it.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

花辞树 2024-11-16 16:05:28

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

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

但是,我还要补充一点,使 X() 方法公开不会造成任何损害,因为该类是内部的,因此该成员已经受到该访问修饰符的限制...也就是说,它实际上已经是内部的了...所以你不妨将其公开!

If you are implicitly implementing an interface I believe that the member must be declared public. In your example, CA attempts to implicitly implement the X() method but isn't declared public. If you want to keep X() as internal then you should use explicit interface implementation.

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

However, I'll also add that making the X() method public wouldn't do any harm anyway as the class is internal so that member is already restricted by that access modifier... That is, it's already effectively internal... So you might as well just make it public!

天邊彩虹 2024-11-16 16:05:28

我知道这个问题被问起已经有一段时间了,但也许我可以解释一下。根据 C# 语言规范,此处发现了您的行为描述的应该是不可能的。因为根据 20.4.2 接口映射,据说实现要么是显式的,要么映射到 public 非静态成员。因此,要么您遇到了与此处描述的情况不同的其他情况,要么您在编译器中发现了错误:)。

I know it has been a while since this question was asked, but maybe I can shed some light on it. According to the C# language specification found here the behavior you described should not be possible. Because under 20.4.2 Interface mapping it is said that the implementation is either explicit or mapped to a public non-static member. So either you have some other scenario than the one you are describing here, or you found a bug in your compiler :).

窝囊感情。 2024-11-16 16:05:28

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

Probably that your "Temp" class is public and IScanner is internal. This is the reason why you get this error. I consider this very annoying since your are forced to implement it explicitly you cannot specify them as abstract or virtual. For the virtual stuff, I was forced to do an implicit internal virtual implementation of the same API and then call the implicit version from the explicit one. Ugly.

乙白 2024-11-16 16:05:28

如果您的目的是向外部隐藏某个实现,您可以像这样显式实现它:

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 里面。由于 ILDialogInternalService内部,因此除了通过反射之外,没有人可以从外部调用它。

If your intention is to hide a certain implementation from outside, you can implement it explicitly like this:

internal class LDialogService : ILDialogService, ILDialogInternalService
{

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

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

In the above code, I want to expose ShowAsync method to the outside but keep SetComponent inside. Since ILDialogInternalService is internal, no one can call it from outside except through Reflection.

雨后咖啡店 2024-11-16 16:05:28

据我所知,您无法实现接口方法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);
    }
}

To all my knowledge you cannot implement interface methods internal. As you stated you can implement them explicitly but then someone can still do ((IScanner)myScanner).SetHardware(hw)

Are you 100% sure your MyScanner implementation does not do something like this:

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

or this:

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

internal partial class MyScanner
{
    void IScanner.SetHardware(Hardware hardware)
    {
        this.SetHardware(hardware);
    }
}
伴随着你 2024-11-16 16:05:28

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

示例:

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://learn.microsoft.com/ en-us/dotnet/csharp/语言参考/语言规范/接口

It's OK to have an internal modifier in an Interface declaration however you CAN'T have ANY modifiers INSIDE the interface, in other words, you can't have any modifier for the interface Members. It's simple as that!

Example:

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 
    {
        ...
    }
}

An interface declaration may declare zero or more members. The members of an interface must be methods, properties, events, or indexers. An interface cannot contain constants, fields, operators, instance constructors, destructors, or types, nor can an interface contain static members of any kind.
All interface members implicitly have public access. It is a compile-time error for interface member declarations to include any modifiers. In particular, interfaces members cannot be declared with the modifiers abstract, public, protected, internal, private, virtual, override, or static.

Reference:
https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/language-specification/interfaces

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文