Подтвердить что ты не робот

Внутренний интерфейс С# с внутренней реализацией

Я поразил то, что я действительно не понимаю.

У меня есть проект, где у меня есть внутренний интерфейс. Класс, который реализует этот интерфейс, также является внутренним. В реализации интерфейса я делаю все члены, которые я реализую, внутренние. Я не делал явной реализации.

У меня есть два интерфейса и два класса, которые реализуют те интерфейсы, где это прекрасно работает.

Он будет выглядеть примерно так:

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 на него, и он не будет компилироваться, что даст мне ошибку, которая: "не может реализовать член интерфейса, потому что он не является общедоступным".

Может ли кто-нибудь объяснить эту несогласованность?

Спасибо

(Обновлено, чтобы исправить опечатку и прояснить некоторый текст)

EDIT: Дополнительная информация

Я запустил код через отражатель, и мои реализации были скомпилированы как явные реализации, хотя они не явны. Отражатель не показывает признаков внутренних ключевых слов. Все, что я могу догадаться, это что-то вроде сбоя в компиляторе, который по какой-то причине позволил мне сделать их внутренними и неявными и что он каким-то образом решил это как явную реализацию.

Я просматривал код несколько раз. Я не могу найти никаких других объяснений.

4b9b3361

Ответ 1

Если вы неявно реализуете интерфейс, я считаю, что член должен быть объявлен открытым. В вашем примере CA пытается неявно реализовать метод X(), но не объявляется общедоступным. Если вы хотите сохранить X() как внутренний, вы должны использовать явную реализацию интерфейса.

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

Однако я также добавлю, что создание открытого метода X() не принесет никакого вреда, поскольку класс является внутренним, так что член уже ограничен этим модификатором доступа... То есть он уже эффективно... Так что вы могли бы просто сделать его общедоступным!

Ответ 2

Я знаю, что прошло некоторое время с тех пор, как был задан этот вопрос, но, возможно, я смогу пролить свет на него. Согласно спецификации языка С#, найденной здесь, описанное вами поведение не должно быть возможным. Поскольку в соответствии с 20.4.2 сопоставление интерфейсов говорится, что реализация является либо явной, либо сопоставлена ​​с нестационарным членом public. Таким образом, либо у вас есть другой сценарий, чем тот, который вы описываете здесь, либо вы обнаружили ошибку в своем компиляторе:).

Ответ 3

Возможно, ваш класс "Temp" является общедоступным, а IScanner является внутренним. Именно по этой причине вы получаете эту ошибку. Я считаю, что это очень раздражает, так как вы вынуждены реализовать его явно, вы не можете указать их как абстрактные или виртуальные. Для виртуального материала мне пришлось сделать неявную внутреннюю виртуальную реализацию того же API, а затем вызывать неявную версию из явной. Некрасиво.

Ответ 4

Насколько я знаю, вы не можете реализовать интерфейсные методы 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

Это нормально, чтобы иметь внутренний модификатор в объявлении интерфейса, но у вас НЕ МОЖЕТ БЫТЬ ЛЮБЫЕ модификаторы ВНУТРИ интерфейса, другими словами, у вас не может быть модификатора для членов интерфейса. Это просто так!

Пример:

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