Компилятор говорит, что я не реализую свой интерфейс, но я? - PullRequest
12 голосов
/ 14 июня 2011

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

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

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

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

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

Чтобы быть ясным

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

string IAccount.SomeMethod()

Почему?

Ответы [ 7 ]

24 голосов
/ 14 июня 2011

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

Общедоступными:

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

Явными:

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

Модификатор доступа по умолчанию в C #: privateесли вы не укажете модификатор доступа.

3 голосов
/ 15 июня 2011

У вас есть 2 основных варианта реализации интерфейсов: неявный или явный.Неявная реализация принимает форму открытого метода или свойства, тогда как явная - в форме метода или свойства, которому предшествует модификатор 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 необходим для компиляции неявной версии.

1 голос
/ 15 июня 2011

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

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

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

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

1 голос
/ 15 июня 2011

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

Ваше объявление класса должно выглядеть так:

class Account : IAccount
{ 
  //Implementation here.
}

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

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

IAccount.SomeMethod()
{
   //Implementation Here
}

вы явно используете интерфейс.

1 голос
/ 14 июня 2011

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

namespace Project.DataAccess.Concrete
{
    public class Account : IAccount    
    {
        public string IAccount.SomeMethod()
        {
            return "Test";
        }
    }
}
1 голос
/ 14 июня 2011

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

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

0 голосов
/ 14 июня 2011
class Account : IAccount    
    {         
    public string SomeMethod()         
    {            
     return "Test";         
    }     
    } 

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

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

class MyClass : IAccount
{
   public int SomeMethod() {}
   public string IAccount.SomeMethod() {}
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...