Использует ли использование также объекты, созданные в конструкторе?

При создании элемента, который реализует IDisposable, Dispose() вызывается в конце блока using также, если выдается исключение, если я прав.

Однако при создании нового элемента ClassB в конструкторе одноразового элемента будет ли объект ClassB также удаляться, если реализован IDisposable?

using (ClassA a = new ClassA(new ClassB()))
{
}

Это может относиться к классам, связанным с Stream. Однако применимо ли это в целом?


person bytecode77    schedule 15.06.2016    source источник
comment
Нет. Он создается не внутри конструктора, а до конструктора.   -  person dymanoid    schedule 15.06.2016
comment
Это было бы испорчено, если бы это было так. Вы можете создать ClassB, который реализует IDisposable, и протестировать примерно столько же нажатий клавиш, сколько и этот вопрос.   -  person paparazzo    schedule 15.06.2016


Ответы (2)


ClassB будет удален только если метод dispose ClassA вызывает для него dispose.

class ClassA : IDisposable
{
    private ClassB b;
    public ClassA (ClassB b) { this.b = b; }
    public void Dispose() { this.b.Dispose(); }
}

Если это не так, вам нужно будет утилизировать его отдельно:

using (ClassB b = new ClassB())
using (ClassA a = new ClassA(b))
{
}
person Trevor Pilley    schedule 15.06.2016
comment
Даже в первом случае исключение в конструкторе ClassA приведет к утечке экземпляра ClassB. - person Servy; 15.06.2016
comment
Так что лучше не доверять никакому классу... Есть ли способ узнать, использует ли класс параметры своего конструктора, кроме декомпиляции? Потоки, кажется, делают это. Но есть ли общая закономерность? - person bytecode77; 15.06.2016
comment
@ bytecode77 Если документально указано, что он избавляется от ресурса, предположим, что он избавится от него. Если это явно не указано, что это так, предположим, что это не так. - person Servy; 15.06.2016
comment
@ bytecode77, на самом деле не рекомендуется удалять внедренные объекты. Пример 1 в этом ответе - плохое решение. Что, если объект ClassB является общим для многих экземпляров ClassA? - person dymanoid; 15.06.2016
comment
Должно безопасно вызывать Dispose несколько раз, поэтому, даже если ClassA избавился от ClassB, если вы использовали второй пример, это не должно вызвать проблемы. - person Trevor Pilley; 15.06.2016
comment
Но тогда объект ClassB находится в удаленном состоянии, и когда другой объект ClassA пытается его использовать, мы получаем, например, ObjectDisposedException, или объект не будет работать должным образом, в зависимости от реализации. - person dymanoid; 15.06.2016
comment
@dymanoid - (первый комментарий) не обязательно, бывают случаи, когда вам может понадобиться это сделать (например, если у вас есть фабричный метод, который возвращает IThing, но реализация Thing нуждается в каком-то другом ресурсе, который равен IDisposable) (второй комментарий) - это правда, это не должно быть обзором кода, я просто отвечаю на вопрос, когда ClassB будет утилизирован... - person Trevor Pilley; 15.06.2016
comment
Вот пример первого сценария (отчасти). Вы просто должны знать, что произойдет с объектом, как только вы передадите его другому объекту. - person Sinatr; 15.06.2016
comment
@dymanoid: если последний пользователь объекта, который обертывает ресурс, ничего не знает о рассматриваемом ресурсе, обертка, скорее всего, будет единственным, что может удалить ресурс. Если оболочка может использоваться как с общими, так и с неразделяемыми ресурсами, ее конструктор должен позволять поставщику ресурса указывать, должен ли новый объект стать владельцем. - person supercat; 17.06.2016

Короткий ответ, нет. Если ClassB реализует IDisposable, вы также должны обернуть его в блок using:

using (var b = new ClassB())
using (var a = new ClassA(b))
{
    // do stuff
}

Имейте в виду, что все, что вы передаете конструктору или любому другому методу, принимающему параметры, оценивается до вызова конструктора или метода.

Некоторые классы, такие как StreamWriter с Stream, удаляют все, что передается через конструктор, но обычно оставляют удаление тому, кто фактически создал экземпляр объекта.

person Groo    schedule 15.06.2016