Реализация IDisposable с пустым Dispose для удобства чтения - PullRequest
3 голосов
/ 10 марта 2011

Мне нравится оператор using () {} для управления областью действия и для удобства чтения.Вы можете не только создавать объекты, использовать их и аккуратно располагать их, но вы также можете использовать их следующим образом:

Предположим, что myInstance является экземпляром MyClass из некоторого другого места в коде - то есть параметра метода или чего-то еще

using (var t = myInstance) {
    t.Foo= "Hello";
    t.Bar= "World";
    ...
}

Определение MyClass:

public class MyClass : IDisposable
{
   public string Foo {get; set;}
   public string Bar {get; set;}
   ...

   public void Dispose() {}
}

Это делает код более аккуратным и удобочитаемым (я чувствую), и, конечно, его легче набирать.Однако для того, чтобы использовать это широко, вы должны реализовать IDisposable.В этом случае MyClass не нужно обрабатывать что-либо в Dispose, поэтому он пуст.

Мой вопрос: есть ли какой-либо недостаток использования IDisposable таким образом?

Я признателен, что уже есть похожие вопросы по SO, но я не думаю, что они касаются использования IDispose для этой цели (или они относятся к конкретным классам).

РЕДАКТИРОВАТЬ:

ОК, так что, думаю, я немного уточнил, но здесь есть более широкий вопрос.Оператор using - это удобный, очень аккуратный способ определения экземпляра за определенный промежуток времени, и тогда вы можете об этом забыть.Кажется несправедливым, что эта способность должна быть ограничена только IDisposable объектами.Да, есть определенная доля лени не только в создании экземпляра, а затем в установке значения null, но использование блока делает его очень конкретным, какова область действия экземпляра. Почему мне нельзя разрешить делать это с не IDisposable классами?

Ответы [ 6 ]

5 голосов
/ 10 марта 2011

Когда вы реализуете IDisposable, вы рекламируете, что ваш класс особенный, и его нужно правильно утилизировать.Не только с таким встроенным кодом, но и когда классы содержат ссылки на ваш класс.Им также нужно будет реализовать IDisposable, чтобы избавиться от вашего экземпляра.Это создает искусственное требование для пользователей вашего класса.

Вы можете использовать область действия для достижения того, что вы хотите:

{
  var _ = instance;
  _.Foo = "Hello"; 
  _.Bar = "World"; 
}

Другой вариант:

instance.With(_ => {
  _.Foo = "Hello";
  _.Bar = "World"; 
});

...

public static class WithExtensions {
  public static void With<T>(this T instance, Action<T> action) {
    action(instance);
  }
}

Этот лучше, потому что то, что происходит, более явное .

Я также вижу боль, которую вы испытываете.Было бы лучше, если бы мы могли определять наши собственные блоки управления (как в Nemerle ).Хотя C # не допускает такую ​​настройку, вам не следует злоупотреблять определенным оператором using, чтобы добиться того, чего вы хотите.Для этого вы можете использовать лямбды, во многом так, как я показал с помощью метода расширения With.Фактически, именно так были сделаны некоторые параллельные «конструкции» в Task Parallel Library .

5 голосов
/ 10 марта 2011

Если ваш класс не нужно утилизировать, нет смысла использовать using.

Вместо этого вы можете сделать нормальный блок:

{ var t = myInstance;
    t.Foo= "Hello";
    t.Bar= "World";
    ...
}

Однако я не вижу цели.

С точки зрения дизайна, вы не должны реализовывать IDisposable без необходимости.
Реализация IDisposable говорит людям, которые используют ваш класс, что он использует дорогие ресурсы и должен быть утилизирован, когда закончите с.
Если это не совсем так, вы просто усложняете их работу.

2 голосов
/ 10 марта 2011

Да, блок using является синтаксическим сахаром для блока try / finally.

1 голос
/ 10 марта 2011

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

public void WorkWithMyInstance(MyInstance t)
{
  t.Foo= "Hello";
  t.Bar= "World";
  ...
}
0 голосов
/ 10 марта 2011

Вы также можете использовать это право?

var myclass = new MyClass
{
MyProperty1 = "Property1",
MyProperty2 = "Property2",
};
0 голосов
/ 10 марта 2011

Вы на самом деле не используете интерфейс, как это было задумано.Согласно документации :

Основное использование этого интерфейса - освобождение неуправляемых ресурсов.

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

Я думаю, что непреднамеренное последствие будет путаницей.

...