C # реализует два разных универсальных интерфейса - PullRequest
2 голосов
/ 12 августа 2009

Я не уверен, что то, что я хочу сделать, является даже хорошей идеей, но в любом случае вот проблема: у меня есть MyClass, который я хочу реализовать двумя различными типами универсального класса IEnumerable, например

public class MyClass : IEnumerable<KeyValuePair<string, string>>,
                       IEnumerable<KeyValuePair<MyEnum, string>>

Теперь проблема заключается в том, что когда я пытаюсь определить необходимые методы из интерфейсов, компилятор жалуется: «Тип« MyClass »уже определяет член с именем« GetEnumerator »с такими же типами параметров». Это потому, что у меня есть два метода:

public IEnumerator<KeyValuePair<MyEnum, string>> GetEnumerator() { ... }
public IEnumerator<KeyValuePair<string, string>> GetEnumerator() { ... }

У меня должен быть GetEnumerator() без параметров из-за интерфейса, и единственное, что отличается, - это тип возвращаемого значения, что недопустимо.

Вот что я вижу в качестве своих вариантов:

  1. Я подумывал о том, чтобы иметь «основной» универсальный тип IEnumerable, который MyClass мог бы реализовать, а затем просто добавление дополнительных методов, отличающихся параметрами, а не просто возвращаемого типа (например, Add), без реализации дополнительного универсального интерфейсы.
  2. Я мог бы создать базовый базовый класс для MyClass, назвать его MyBaseClass<T>, и он бы реализовал IEnumerable<KeyValuePair<T, string>>. Тогда у меня были бы разные версии MyClass, например MyClass<string> и MyClass<MyEnum>.

Что здесь предпочтительнее, или я что-то упустил, что было бы еще лучшим решением?

Ответы [ 4 ]

14 голосов
/ 12 августа 2009

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

public class MyClass : IEnumerable<KeyValuePair<string, string>>,
                   IEnumerable<KeyValuePair<MyEnum, string>>
{
    IEnumerator<KeyValuePair<MyEnum, string>> IEnumerable<KeyValuePair<MyEnum, string>>.GetEnumerator()
    {
        // return your enumerator here
    }

    IEnumerator<KeyValuePair<string, string>> IEnumerable<KeyValuePair<string, string>>.GetEnumerator()
    {
        // return your enumerator here
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        var me = this as IEnumerable<KeyValuePair<string, string>>;
        return me.GetEnumerator();
    }
}

Однако, поскольку IEnumerable <> является производным от IEnumerable, вам нужно будет выбрать тот, который вы хотите вернуть из вызова IEnumerable.GetEnumerator ().

2 голосов
/ 12 августа 2009

Вы можете использовать явную реализацию интерфейса для реализации интерфейсов с конфликтующими методами. Однако, если вы реализуете два интерфейса IEnumerable<T>, это вызовет некоторые довольно раздражающие проблемы для таких вещей, как циклы foreach. Однажды я попробовал это для чего-то и быстро вернулся к реализации интерфейса 1 IEnumerable, а другой предложил как свойство объекта.

2 голосов
/ 12 августа 2009

Вы можете развернуть каждый интерфейс следующим образом:

IEnumerable<KeyValuePair<string, string>> IEnumerable<KeyValuePair<string, string>>.GetEnumerator() { ... }
IEnumerator<KeyValuePair<MyEnum, string>> IEnumerator<KeyValuePair<MyEnum, string>>.GetEnumerator() { ... }
0 голосов
/ 12 августа 2009

Одним из вариантов будет явная реализация интерфейсов .

Даунсайд - вам всегда нужно будет разыграть MyClass.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...