Давний joelonsoftware подписчик, 1-й разовый плакат stackoverflow.
Я хочу знать, "как безопасно" я могу сделать следующий (C#):
Form formDlg = new Form();
TextBox box = new TextBox();
formDlg.Controls.Add( box );
formDlg.ShowDialog();
formDlg.Dispose();
string sUserEntered = box.Text; // After parent Dispose'd!
На практике это (по-видимому), работает, потому что поле (как Управление) имеет частное текстовое поле (строка), который оно использует для реализации ее текстового свойства после того, как ее дескриптор окна уничтожается.
Я не буду удовлетворен общим ответом, что "Вы не можете получить доступ к объекту после того, как он Расположен" потому что (1) я не могу найти никакой подобный общий запрет в документах MS, (2) я не получаю доступ к неуправляемому ресурсу и (3) этот код не выдает исключения (включая ObjectDisposedException).
Я хотел бы сделать это так, я могу создать и использовать объединенный метод "ShowAndDispose" для снижения риска упущения всегда звонить, Располагают () после ShowDialog ().
Для усложнения поведение изменяется в отладчике. Если я повреждаюсь, прежде Располагают (); затем поле Quick Watch и выполняет развертку в его базовый класс Управления; затем шаг мимо Располагает (); затем поле. Текстовые возвраты""! В другом поле сценариев. Текст возвращает вводимый пользователем текст.
Этот код запускает деталь реализации без проблем. Свойство Control.Text кэшируется классом Control, поэтому удаление TextBox не вызывает исключения ObjectDisposed.
Это довольно редко, кстати, множество методов получения и установки свойств элемента управления генерируют сообщение Windows, чтобы запросить значение свойства у собственного элемента управления Window. Вы столкнетесь с этим, потому что свойство Handle больше не действует. Примечательно также то, что средство установки свойства Text обновляет кэшированное значение, но также генерирует сообщение Window для обновления собственного элемента управления. Баба здесь.
Я полагаю, это просто общий интерес, никогда не используйте такой код в своей программе. Что ж, ты узнаешь достаточно быстро.
Сценарий с отладчиком заставляет меня думать, что то, что вы делаете, ненадежно, чтобы проверить это, попробуйте хотя бы следующее:
formDlg.Dispose();
Application.DoEvents();
GC.Collect();
GC.WaitForPendingFinalizers();
string sUserEntered = box.Text; // After parent Dispose'd!
Я поместил значение sUserEntered
в публичное свойство, чтобы к нему можно было получить доступ:
public string UserInput
{
get;
set;
}
public frmDialog()
{
//
// The InitializeComponent() call is required for Windows Forms designer support.
//
InitializeComponent();
//
// TODO: Add constructor code after the InitializeComponent() call.
//
}
void Button1Click(object sender, EventArgs e)
{
UserInput = userInput.Text;
this.Dispose();
}
Затем в моей главной форме:
using (dialog = new frmDialog())
{
dialog.ShowDialog();
stringUserInput.Text = dialog.UserInput;
};
Вы можете использовать оператор using, чтобы гарантировать удаление объекта, когда вы закончите с ним:
using(Form frmDialog = new Form())
{
//Do stuff
}
frmDialog будет удален после блока я считаю, что побежал.
Мне пришло в голову, что я могу создать и использовать класс, производный от формы, с методом BeginShowDialog (), который вызывает ShowDialog () и EndShowDialog () метод, который вызывает Dispose (). «Begin» в имени метода сделает необходимость вызова «End» более очевидной.
Я скучаю по детерминированному уничтожению C ++ локальных переменных при выходе из области видимости.