Controlos claros não os eliminam – qual é o risco?
-
21-09-2019 - |
Pergunta
Existem vários tópicos (a, b, c etc.) sobre o fato de que Claro() inserir itens nos contêineres de componentes .NET não Descartar eles(chamando Dispose(verdadeiro).
Na maioria das vezes, IMHO, os componentes Clear-ed não são mais usados no aplicativo, portanto, ele precisa ser explicitamente descartado após limpá-los dos contêineres pai.
Talvez seja uma boa ideia essa coleção Clear
método tinha um parâmetro bool dispose
que quando verdadeiro também descarta os elementos da coleção antes de removê-los da lista?
Solução
Pedir modificações como essa é inútil, a equipe do Windows Forms foi dissolvida há algum tempo.Está em modo de manutenção, apenas são considerados problemas de segurança e incompatibilidades de SO.
Caso contrário, é bastante simples criar seu próprio método para fazer isso:
public static class ExtensionMethods {
public static void Clear(this Control.ControlCollection controls, bool dispose) {
for (int ix = controls.Count - 1; ix >= 0; --ix) {
if (dispose) controls[ix].Dispose();
else controls.RemoveAt(ix);
}
}
}
Agora você pode escrever:
panel1.Controls.Clear(true);
Outras dicas
Respondendo à pergunta “qual é o risco”, o risco (ou um risco) é ficar sem puxadores de janela, embora possa demorar um pouco.
Eu tenho um "designer de janelas" que gera uma janela a partir de um script.Cada vez que altero o script, a janela é reconstruída (os controles são limpos e adicionados novamente).Com uma janela particularmente complexa, e usando Controls.Clear()
a cada vez, depois de muitas dezenas de atualizações, acabarei recebendo uma exceção "não há mais identificadores de janela" e não poderei criar mais controles.
Fácil o suficiente para substituir o Controls.Clear()
ligue com algo como:
Controls.Cast<Control>().ForEach(c => c.Dispose());
A resposta do @Hans Passant é boa, mas no caso de programação assíncrona, você deve considerar remover o objeto antes de descartá-lo para evitar que algum thread itere sobre um objeto descartado.
Mais ou menos algo assim:
public static class ExtensionMethods {
public static void Clear(this Control.ControlCollection controls, bool dispose) {
for (int ix = controls.Count - 1; ix >= 0; --ix) {
var tmpObj = controls[ix];
controls.RemoveAt(ix);
if (dispose) tmpObj.Dispose();
}
}
}