Oh boy, the passion around GOTO statements in C#; I dread even asking this question.
So many questions similar to this; that also makes me a bit nervous. But I am serious.
Please resist the responses that simply dismiss the GOTO statement wholesale.
However, I am a little stumped to see why this implementation is not ideal for GOTO:
public event CancelEventHandler DeleteSnapshotStarted;
public event AsyncCompletedEventHandler DeleteSnapshotCompleted;
public void DeleteSnapshot(Guid documentId, Action<Exception> callback)
{
if (!this.Snapshots.Where(x => x.DocumentId == documentId).Any())
throw new Exception("Snapshot not found; ensure LoadSnapshots()");
// define action
var _Action = new Action(() =>
{
// preview
bool _Cancelled = false;
if (DeleteSnapshotStarted != null)
{
CancelEventArgs _CancelArgs = new CancelEventArgs { };
DeleteSnapshotStarted(this, _CancelArgs);
if (_CancelArgs.Cancel)
{
_Cancelled = true;
goto END;
}
}
// execute
Exception _Error = null;
try
{
Proxy.CoreService.DeleteSnapshot(documentId);
LoadSnapshots(null);
}
catch (Exception ex) { _Error = ex; }
END:
// complete
if (DeleteSnapshotCompleted != null)
{
AsyncCompletedEventArgs _CompleteArgs =
new AsyncCompletedEventArgs(_Error, _Cancelled, null);
DeleteSnapshotCompleted(this, _CompleteArgs);
}
// bubble error
if (_Error != null)
throw _Error;
});
// run it
if (callback == null) { _Action(); }
else
{
using (BackgroundWorker _Worker = new BackgroundWorker())
{
_Worker.DoWork += (s, arg) => { _Action(); };
_Worker.RunWorkerCompleted += (s, arg) => { callback(arg.Error); };
_Worker.RunWorkerAsync();
}
}
}
** I give – I’ll avoid GOTO! :D**
Here’s what seems best:
public event CancelEventHandler DeleteSnapshotStarted;
public event AsyncCompletedEventHandler DeleteSnapshotCompleted;
public void DeleteSnapshot(Guid documentId, Action<Exception> callback)
{
if (!this.Snapshots.Where(x => x.DocumentId == documentId).Any())
throw new Exception("Snapshot not found; ensure LoadSnapshots()");
// define action
var _Action = new Action(() =>
{
// preview
CancelEventArgs _CancelArgs = new CancelEventArgs { };
if (DeleteSnapshotStarted != null)
DeleteSnapshotStarted(this, _CancelArgs);
// execute
Exception _Error = null;
if (!_CancelArgs.Cancel) try
{
Proxy.CoreService.DeleteSnapshot(documentId);
LoadSnapshots(null);
}
catch (Exception ex) { _Error = ex; }
// complete
if (DeleteSnapshotCompleted != null)
DeleteSnapshotCompleted(this,
new AsyncCompletedEventArgs(null, _CancelArgs.Cancel, null));
// bubble
if (_Error != null)
throw _Error;
});
// run it
if (callback != null)
{
using (BackgroundWorker _Worker = new BackgroundWorker())
{
_Worker.DoWork += (s, arg) => { _Action(); };
_Worker.RunWorkerCompleted += (s, arg) =>
{ callback(arg.Error); };
_Worker.RunWorkerAsync();
}
}
else
_Action();
}
Thanks everyone.
Yes, you even already have the flag variable:
if (!this.Snapshots.Where(x => x.DocumentId == documentId).Any()) throw new Exception("Snapshot not found; ensure LoadSnapshots()"); // define action var _Action = new Action(() => { // preview bool _Cancelled = false; if (DeleteSnapshotStarted != null) { CancelEventArgs _CancelArgs = new CancelEventArgs { }; DeleteSnapshotStarted(this, _CancelArgs); if (_CancelArgs.Cancel) { _Cancelled = true;goto END;} } if(!_Cancelled) { // execute Exception _Error = null; try { Proxy.CoreService.DeleteSnapshot(documentId); LoadSnapshots(null); } catch (Exception ex) { _Error = ex; } }END:// complete if (DeleteSnapshotCompleted != null) { AsyncCompletedEventArgs _CompleteArgs = new AsyncCompletedEventArgs(_Error, _Cancelled, null); DeleteSnapshotCompleted(this, _CompleteArgs); } // bubble error if (_Error != null) throw _Error; });