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

Компилятор говорит, что я не реализую свой интерфейс, но я?

Хорошо, у меня есть два пространства имен. Один содержит мой интерфейс, а один содержит класс реализации. Вот так:

namespace Project.DataAccess.Interfaces
{
    public interface IAccount
    {
        string SomeMethod();
    }
}

namespace Project.DataAccess.Concrete
{
    class Account : Project.DataAccess.Interfaces.IAccount
    {
        string SomeMethod()
        {
            return "Test";
        }
    }
}

С помощью этого кода я получаю сообщение об ошибке:

'Project.DataAccess.Concrete.Account' не реализует член интерфейса 'Project.DataAccess.Interfaces.IAccount.SomeMethod'. "Project.DataAccess.Concrete.Account.SomeMethod" не может реализовать член интерфейса, поскольку он не является общедоступным.

Если я создаю класс и метод public, он работает нормально. Но если я вместо этого квалифицирую имя метода с именем интерфейса, это также исправляет его. Зачем? Пример:

namespace Project.DataAccess.Concrete
{
    class Account : Project.DataAccess.Interfaces.IAccount
    {
        string IAccount.SomeMethod()
        {
            return "Test";
        }
    }
}

Почему это исправить? И почему это должно быть общедоступным, если я этого не делаю?

Чтобы быть четким

Мне хорошо известно, что это делает его общедоступным. Создание подписи метода выглядит так: БЕЗ создания каких-либо публичных исправлений:

string IAccount.SomeMethod()

Почему?

4b9b3361

Ответ 1

Реализации интерфейса должны быть общедоступными или явными:

Public:

class Account : IAccount
{
    public string SomeMethod()
    {
        return "Test";
    }
}

Явное:

class Account : IAccount
{
    string IAccount.SomeMethod()
    {
        return "Test";
    }
}

Модификатор доступа по умолчанию в С# равен private, если вы не указали модификатор доступа.

Ответ 2

У вас есть 2 основных варианта при реализации intefaces: неявный или явный. Неявная реализация принимает форму открытого метода или свойства, а явный - в виде метода или свойства, предваряемого модификатором IFoo., который в противном случае не является общедоступным.

interface IFoo
{
    void Bar();
}

class FooA : IFoo
{
    public void Bar() { }
}

class FooB : IFoo
{
    void IFoo.Bar() { }
}

Разница здесь в том, что в случае FooA, void Bar является частью общедоступного API класса. Код может вызывать Bar через экземпляр класса.

FooA foo = new FooA(); 
foo.Bar(); // legal

В случае FooB, void Bar не является частью общедоступного API класса. Этот метод все еще можно вызвать, но он должен быть явно вызван через интерфейс.

FooB foo = new FooB();
foo.Bar(); // not legal
IFoo myFoo = foo;
myFoo.Bar(); // legal

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

Ответ 3

Методы реализации интерфейса должны быть общедоступными. В вашем последнем случае вы объявляете это явно. Это описание о явной реализации интерфейса.

Явный член интерфейса реализации имеют разные характеристики доступности, чем другие члены. Поскольку явный реализации интерфейса никогда не доступны через их полностью квалифицированное имя в вызове метода или доступа к собственности, они находятся в смысл частный. Однако, поскольку они могут доступ через интерфейс Например, они в некотором смысле общественности.

Ответ 4

'Project.DataAccess.Concrete.Account.SomeMethod' не может реализовать член интерфейса , поскольку он не является общедоступным

namespace Project.DataAccess.Concrete
{
    public class Account : IAccount    
    {
        public string IAccount.SomeMethod()
        {
            return "Test";
        }
    }
}

Ответ 5

В объявлении класса не упоминается, что вы будете внедрять IAccount.

Ваше объявление класса должно выглядеть следующим образом:

class Account : IAccount
{ 
  //Implementation here.
}

Кроме того, происходит то, что вы используете уровень защиты по умолчанию для Account, а уровень защиты не является "общедоступным", но интерфейс (IAccount) по умолчанию определяет общедоступные методы.

Итак, когда вы вводите имена классов и методов в public, вы фактически реализуете интерфейс. Аналогично, когда вы объявляете SomeMethod как

IAccount.SomeMethod()
{
   //Implementation Here
}

то, что вы делаете, это Явно реализую интерфейс.

Ответ 6

Я думаю, что объявление явно с помощью string IAccount.SomeMethod() работает, потому что .NET знает, что эту реализацию метода можно получить только через интерфейс, и поэтому он переносит видимость общественности из интерфейса. Другими словами, поскольку вы явно говорите, что это член интерфейса, компилятор может подразумевать, что он должен быть общедоступным, поэтому вам не нужно повторно указывать очевидное.

Это также обсуждается здесь: http://msdn.microsoft.com/en-us/library/aa664591%28v=vs.71%29.aspx

Это ошибка времени компиляции для явный член интерфейса для включения доступа модификаторы, и это время компиляции ошибка включения модификаторов абстрактный, виртуальный, переопределить или статичным.

Явный член интерфейса реализации имеют разные характеристики доступности, чем другие члены. Поскольку явный реализации интерфейса никогда не доступны через их полностью квалифицированное имя в вызове метода или доступа к собственности, они находятся в смысл частный. Однако, поскольку они могут доступ через интерфейс Например, они в некотором смысле общественности.

Ответ 7

class Account : IAccount    
    {         
    public string SomeMethod()         
    {            
     return "Test";         
    }     
    } 

Скажите вашему классу реализовать интерфейс. Использование имени Interface.Method явно реализует метод (но я не уверен, почему и как), и вам нужно сделать их общедоступными.

Вы хотите использовать Interface.Method для явного внедрения требования к интерфейсу, когда класс уже имеет член с тем же именем

class MyClass : IAccount
{
   public int SomeMethod() {}
   public string IAccount.SomeMethod() {}
}