Я работаю над приложением с графическим интерфейсом, которое в значительной степени полагается на Action<>
делегатов для настройки поведения наших инструментов пользовательского интерфейса.Мне интересно, есть ли потенциальные проблемы в том, как мы это делаем, например, сохраняет ли реализация ссылки на захваченные переменные, экземпляры классов, которые объявляют делегатов и т. Д.?
Итак, допустим, у нас есть класс MapControl
, который обертывает элемент управления с графическим интерфейсом.Карта имеет различные виды инструментов (Рисование, Выбор и т. Д.), Представленные интерфейсом ITool
.Вы можете установить инструмент с помощью StartTool()
, но одновременно активным может быть только один инструмент, поэтому при установке другого инструмента предыдущий останавливается с помощью StopTool()
.Когда инструмент остановлен, выполняется указанный делегатом обратного вызова вызывающий.
public class MapControl
{
ITool _currentTool;
Action<IResult> _onComplete;
public void StartTool(ToolEnum tool, Action<IResult> onComplete) {
//If tool is active, stop it first
if (_currentTool != null) StopTool();
_onComplete = onComplete;
//Creates a tool class, etc.
_currentTool = CreateTool(tool) as ITool;
}
public void StopTool() {
//Execute callback delegate
IResult result = _currentTool.GetResult();
if (_onComplete != null)
_onComplete(result);
//Nix the references to callback and tool
_onComplete = null;
_currentTool = null;
}
}
В классе ViewModel
приложения мы устанавливаем некоторый инструмент, подобный этому:
class ViewModel
{
private MapControl _mapControl = new MapControl();
public void SetSomeTool()
{
//These variables will be captured in the closure
var someClassResource = this.SomeClassResource;
var someLocalResource = new object();
//Start tool, specify callback delegate as lambda
_mapControl.StartTool(ToolEnum.SelectTool, (IResult result) => {
//Do something with result and the captured variables
someClassResource.DoSomething(result, someLocalResource);
});
}
}
В нашем случаеКласс ViewModel
присоединен к главному окну приложения WPF, и в течение времени жизни приложения может быть только один экземпляр ViewModel
.Изменит ли это что-нибудь, если бы это было не так, и классы, которые объявляют делегатов, были бы более кратковременными?
Мой вопрос: правильно ли я избавляюсь от делегатов обратного вызова?Существуют ли сценарии, в которых это может вызвать переполнение памяти, если удерживать ссылки, которых не должно быть?
В целом, каков безопасный и правильный способ удаления анонимных делегатов?