При разработке класса следует ли согласованность поведения предпочтительнее обычной практики программирования? Чтобы привести конкретный пример:
Общее соглашение таково: если классу принадлежит объект (например, он его создал), он отвечает за его очистку после завершения. Конкретным примером может быть .NET, если ваш класс владеет IDisposable
объектом, он должен утилизировать его в конце своей жизни. И если у вас нет этого, не трогайте его.
Теперь, если мы посмотрим на StreamWriter
класс в .NET, мы можем найти в документации, что он закрывает основной поток, когда он закрывается / удаляется. Это необходимо в тех случаях, когда StreamWriter
создается экземпляр путем передачи имени файла, поскольку модуль записи создает базовый файловый поток и, следовательно, должен его закрывать. Однако можно также передать во внешний поток, который автор также закрывает.
Это раздражало меня кучу раз (да, я знаю, что вы можете сделать не закрывающуюся оболочку, но это не главное), но, очевидно, Microsoft приняла решение, что более последовательно всегда закрывать поток независимо от того, откуда он пришел.
Когда я сталкиваюсь с таким шаблоном в одном из моих классов, я обычно создаю ownsFooBar
флаг, который устанавливается в false в тех случаях, когда FooBar
вводится через конструктор, и в true в противном случае. Таким образом, ответственность за его очистку передается вызывающей стороне, когда он передает экземпляр явно.
Теперь мне интересно, может быть, последовательность должна быть в пользу перед лучшей практикой (или, может быть, моя лучшая практика не настолько хороша)? Есть аргументы за / против?
Изменить для уточнения
Под «согласованностью» я подразумеваю: согласованное поведение класса, всегда берущее на себя ответственность (и закрывающее поток), против «наилучшей практики» - владеть объектом только в том случае, если вы его создали или явно передали право владения.
Как для примера, где это enoying:
Предположим, у вас есть два заданных класса (из какой-то сторонней библиотеки), которые принимают поток, чтобы что-то с ним делать, например, создавать и обрабатывать некоторые данные:
public class DataProcessor
{
public Result ProcessData(Stream input)
{
using (var reader = new StreamReader(input))
{
...
}
}
}
public class DataSource
{
public void GetData(Stream output)
{
using (var writer = new StreamWriter(output))
{
....
}
}
}
Теперь я хочу использовать это так:
Result ProcessSomething(DataSource source)
{
var processor = new DataProcessor();
...
var ms = new MemoryStream();
source.GetData(ms);
return processor.ProcessData(ms);
}
Это не удастся, за исключением Cannot access a closed stream
обработки данных. Это немного сконструировано, но должно проиллюстрировать это. Существуют различные способы исправить это, но, тем не менее, я чувствую, что работаю над тем, что мне не нужно.