Большую часть времени я использую явную реализацию интерфейса. Вот основные причины.
Рефакторинг безопаснее
При изменении интерфейса лучше, если компилятор сможет это проверить. С неявной реализацией дело обстоит сложнее.
На ум приходят два распространенных случая:
Добавление функции к интерфейсу, где существующий класс, реализующий этот интерфейс, уже имеет метод с той же сигнатурой, что и новый. Это может привести к неожиданному поведению и несколько раз сильно укусить меня. Это трудно «увидеть» при отладке, потому что эта функция, скорее всего, не находится в других методах интерфейса в файле (проблема самодокументирования, упомянутая ниже).
Удаление функции из интерфейса. Неявно реализованные методы будут внезапно мертвым кодом, но явно реализованные методы будут обнаружены ошибкой компиляции. Даже если мертвый код хорошо хранить, я хочу, чтобы меня заставили его просмотреть и продвигать.
К сожалению, в C # нет ключевого слова, которое заставляет нас помечать метод как неявную реализацию, чтобы компилятор мог выполнять дополнительные проверки. Виртуальные методы не имеют ни одной из вышеперечисленных проблем из-за обязательного использования 'override' и 'new'.
Примечание: для фиксированных или редко меняющихся интерфейсов (обычно из API поставщика) это не проблема. Однако для моих собственных интерфейсов я не могу предсказать, когда и как они изменятся.
Самодокументируется
Если я вижу «public bool Execute ()» в классе, потребуется дополнительная работа, чтобы выяснить, что это часть интерфейса. Кому-то, вероятно, придется прокомментировать это, сказав это, или поместить его в группу других реализаций интерфейса, и все это будет под областью или групповым комментарием, говорящим «реализация ITask». Конечно, это работает только в том случае, если заголовок группы не находится за кадром.
Тогда как: 'bool ITask.Execute ()' ясен и недвусмысленен.
Четкое разделение реализации интерфейса
Я считаю, что интерфейсы более «общедоступны», чем общедоступные методы, потому что они созданы так, чтобы отображать лишь небольшую часть поверхности конкретного типа. Они сводят тип к возможности, поведению, набору признаков и т. Д. И в реализации, я думаю, полезно сохранить это разделение.
Когда я просматриваю код класса, когда я сталкиваюсь с явными реализациями интерфейса, мой мозг переключается в режим «контракта кода». Часто эти реализации просто перенаправляют к другим методам, но иногда они будут выполнять дополнительную проверку состояния / параметров, преобразование входящих параметров для лучшего соответствия внутренним требованиям или даже перевод для целей управления версиями (то есть несколько поколений интерфейсов все переходят к общим реализациям).
(Я понимаю, что паблики также являются контрактами кода, но интерфейсы намного сильнее, особенно в кодовой базе, управляемой интерфейсами, где прямое использование конкретных типов обычно является признаком того, что код предназначен только для внутреннего использования.)
Связано: Причина 2 выше, Джон.
И так далее
Плюс преимущества, уже упомянутые в других ответах здесь:
Проблемы
Это еще не все веселье и счастье. В некоторых случаях я придерживаюсь имплицитов:
- Типы значений, потому что для этого потребуется упаковка и более низкая производительность. Это не строгое правило и зависит от интерфейса и того, как он предназначен для использования. Iomparable? Скрытый. IFormattable? Наверное, явно.
- Тривиальные системные интерфейсы, у которых есть методы, которые часто вызываются напрямую (например, IDisposable.Dispose).
Кроме того, может быть затруднительно выполнять приведение, когда у вас действительно есть конкретный тип и вы хотите вызвать явный метод интерфейса. Я справляюсь с этим одним из двух способов:
- Добавьте паблики и отправьте им методы интерфейса для реализации. Обычно это происходит с более простыми интерфейсами при внутренней работе.
- (Мой предпочтительный метод) Добавьте
public IMyInterface I { get { return this; } }
(который должен быть встроен) и вызовите foo.I.InterfaceMethod()
. Если несколько интерфейсов нуждаются в этой возможности, расширьте имя за пределами I (по моему опыту, мне редко это нужно).
person
scobi
schedule
15.08.2014