Я собирался задать этот же вопрос, но решил быть очень настороженным и провести обширный поиск - чтобы избежать дублирования. Затем я нашел это - я редактировал заголовок в надежде, что он станет более популярным, потому что он должен.
Во-первых, мы должны знать, что пустой интерфейс, такой как этот, также известен как интерфейс маркера - this other, unanswered, SO discusses concerns marker interfaces, и ответ Скотта Вишневси (в настоящее время сверху) интересен, когда рассматривается остальная часть того, что я собираюсь сказать.
В исследовании пустых интерфейсов вы обычно натыкаетесь the MSDN topic concerning Code Analysis warning CA1040 который специфически наводит на мысли, что пустые интерфейсы, которые не реализуют по крайней мере, два других следует избегать.
Под этим маркером - и, конечно, не обязательно подразумевает, что рекомендации по кодированию Microsoft де-факто - в вашем примере, это именно то, что вы делаете (и то, что я хочу сделать в моем текущем проекте), и поэтому оно пройти MS 'собственный тест лакмуса. В результате я рад сказать «да, такой интерфейс вполне разумный».
Для оправдания, и я думаю, что особенно хороший пример причины, почему Переключите «по крайней мере, два интерфейса» находится на этом правиле аналогична ситуации я нахожусь в:
public interface IReadsAResource
{
public byte[] Read(string id);
}
public interface IWritesAResource
{
//returns the id
public string Write(byte[] resource);
}
Учитывая эти два интерфейса, теперь я могу написать компонент, который прямо заявляет, что нужно только для чтения или записи:
public class NeedsRead
{
private readonly IReadsAResource Reader;
public NeedsRead(IReadsAResource reader){ Reader = reader; }
}
public class NeedsWrite
{
private readonly IWritesAResource Writer;
public NeedsWrite(IWritesAResource writer){ Writer = writer; }
}
я теперь, как правило, выбрать для реализации этого интерфейса на одном классе ResourceReaderWriter
, учитывая, что хранилище данных для ресурсов будет req Зависимости uire, которые разделяют обе реализации метод, передавая экземпляр, что когда либо интерфейс необходимо:
var needsRead = new NeedsRead(new ResourceReaderWriter(/* dependencies */));
var needsWrite = new NeedsWriter(new ResourceReaderWriter(/* dependencies */));
Но тогда, что если у меня есть класс, который должен как читать и записи ресурсов? С интерфейсом экосистемы в настоящее время на месте, мне нужно два параметра конструктора:
public class NeedsReadAndWrite{
public NeedsReadAndWrite(IReadsAResource reader, IWritesAResource writer){
/* reader/writer local variables elided */
}
}
Не такой трудности, вы можете сказать, но это вызывает две проблемы:
- Смысл в том, что у нас есть два отдельных экземпляры, которые отвечают за чтение и запись ресурсов; поэтому наш класс не может быть уверен, что оба они согласуются друг с другом. Точно так же он не может быть уверен, что состояние управляется правильно между ними.
- Как звонящий, я могу, конечно, обойти это, создав сначала один экземпляр и передав его для обоих параметров. Но это забирает мою способность создавать объект в одном слое, а просто кажется странным.
Любой, кто застрял со мной так долго будет видеть, куда я иду сейчас :)
Элегантное решение ввести интерфейс для такого типа, который поддерживает как чтение и запись:
//denotes a component that can both read and write
public interface IReadsAndWritesAResource : IReadsAResource, IWritesAResource
{
}
С помощью этого интерфейса, наш проблематично типа может быть повторно записан в виде
public class NeedsReadAndWrite{
public NeedsReadAndWrite(IReadsAndWritesAResource readerWriter){
/* local variable assignment elided */
}
}
И обе эти проблемы теперь являются побочными.
Аналогичным образом становится простым создание базового прокси-типа, реализующего этот новый интерфейс, путем ввода экземпляров считывателя и записи и пересылки вызовов чтения/записи на них.
Я думаю, что этот пример демонстрирует, почему вы, или, возможно, даже должны, используйте интерфейсы маркеров, которые объединяют два или более других.
И почему я внезапно появляется как «user123432»? Это не мой идентификатор на StackOverflow. – redman
Есть ли [это] (http://stackoverflow.com/users/123432/user123432) ваши вопросы? Во всяком случае, вы можете посетить [meta.stackoverflow.com] (http://meta.stackoverflow.com), чтобы проверить наличие ошибок. – Boldewyn
Оказывается, мое отображаемое имя в моем профиле было уничтожено. Застигнутый мной врасплох, я этого не делал раньше. – redman