yepi Ответов: 4

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


Попытка реализовать IList< T> следующим образом:
public class My<T> : IList<T>
{
   public bool Add(T itemm) {...}
   ...
}

Это не будет компилироваться, так как возвращаемый тип - 'bool' вместо 'void' интерфейса, несмотря на то, что реализованное добавление может использоваться везде, где требуется интерфейсом. :
IList<int> list = new My<int>(); //Had it compiled....
list.Add(10);
...
Это, конечно, относится только к возвращаемому типу void.

Есть ли какой-нибудь способ сделать так, чтобы имплантация соответствовала интерфейсу?

Спасибо,

Дэн

Karthik_Mahalingam

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

4 Ответов

Рейтинг:
8

yepi

Решение №4 (по Филипп Мори, и прописано Ричард Диминг) является самым чистым.
Поскольку в нем была небольшая опечатка вот рабочая версия:

public class My<T> : IList<T>>
{
   void ICollection<T>.Add(T item) //Ilist<T> inherits Add from ICollection<T>
   {
      Add(item);
   }
   public bool Add(T item) {...}
   //Another example:
   void IList<T>.Insert(int index, T item)
   {
      Insert(index, item);
   }
   public bool Insert(int index, T item) {...}
}


Рейтинг:
15

yepi

Очевидное решение (как засвидетельствовано OriginalGriff) есть:

public class My<T>: IList<T>
{
   public bool AddItem(T item) {...}
   public void Add(T item)
   {
      AddItem(item); //Extra call just to keep the interface happy
   }
}

Это решение немного массово, так как оно имеет два способа использования функциональности
void Add(T item)
i.e.
Add(item); and
AddItem(item);
with the former (the one that implements the interface!) being less efficient.

и я искал "более чистый".

Обратите внимание, что "void" - это специальный тип возврата: вы не указываете "return void" в методе, и я не ищу общей ковариации типа возврата, а просто способ избежать проверки типа результата на [неуказанный] void, т. е. рассматривайте тип возврата void как "совпадающий с любым типом", а не "совпадающий только с void".

спасибо
Дэн.


Richard Deeming

Решение Филиппа (№4) было бы чище.

public class My<T> : IList<T>
{
   public bool Add(T item) {...}
   void ICollection<T>.Add(T item) { Add(item); }
   ...
}

Рейтинг:
1

Philippe Mori

Вы можете явно реализовать интерфейс... но я не уверен на 100% в синтаксисе, так как интерфейс является универсальным.

Для не универсального интерфейса вы просто удаляете спецификатор доступа и добавляете имя интерфейса и точку перед именем метода:

void InterfaceName.MethodName(...)


Я не уверен, что компилятор все еще будет жаловаться. Я так не думаю...


Richard Deeming

Определенно лучшее решение. :)

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

public class My<T> : IList<T>
{
   public bool Add(T item) {...}
   void ICollection<T>.Add(T item) { Add(item); }
}

yepi

Спасибо, Ричард, это выглядит намного чище.
обратите внимание, что правильный синтаксис - " void ICollection

Рейтинг:
1

OriginalGriff

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

            public void Add(T item)
                {
                ...
                }
            public bool Add(T item)
                {
                ...
                }
...
Add(new Item);
Который Add ты будешь звонить?
Ваш единственный вариант-создать новый метод с другим именем:
public void Add(T item)
    {
    ...
    }
public bool AddIfPossible(T item)
    {
    ...
    return true;
    }


yepi

Это решение делает класс массовым (чего я хотел избежать и посмотреть, есть ли у кого-нибудь "более чистое" решение)
Это выглядит так:
открытый класс Мой

OriginalGriff

Вы не можете - нет никакого "более чистого решения", потому что то, что вы пытаетесь сделать, это сделать его более грязным, и компилятор не позволит вам это сделать!