哦,男孩,对C#中GOTO声明的热情;我甚至不敢问这个问题。
这么多类似的问题;这也让我有点紧张但我很认真。
请拒绝仅仅驳回批发GOTO声明的回复。
然而,我有点难以理解为什么这个实现不适合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();
}
}
}
**我给 - 我会避免GOTO! :d **
以下是最佳效果:
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();
}
谢谢大家。
答案 0 :(得分:8)
是的,您甚至已经拥有了标志变量:
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; });
答案 1 :(得分:4)
更改
if (_CancelArgs.Cancel)
{
_Cancelled = true;
goto END;
}
到此:
_Cancelled = _CancelArgs.Cancel;
和END:对此:
if(!Cancelled)
{
// complete...
答案 2 :(得分:3)
原则上,为了便于阅读,值得避免代码中的非本地分支。在您的情况下,可以使用标志变量重构控制流。有关详细信息,请参阅@NeilN和@minitech答案。
在实践中,有时候(在极少数情况下:)使用goto
来解决复杂的控制场景流是很有用的,其中普通的if/else/break/while/for
结构会比必要的更加嵌套或复杂。
goto(我现在能想到的)最好的“好”用法是打破一个深度嵌套的循环集,而不需要在每次循环迭代上进行额外的条件检查。从单一级别的嵌套中,您可以使用break
- 但是对于许多嵌套级别,它会变得更加痛苦。这是一个例子:
// Column-ordered, first value search:
int valueFound = 0;
for (int i = 0; i < x; i++)
{
for (int j = 0; j < y; j++)
{
if (array[j, i] < targetValue)
{
valueFound = array[j, i];
goto Found;
}
}
}
Console.WriteLine("No value was found.");
return;
Found:
Console.WriteLine("The number found was {0}.", valueFound);
答案 3 :(得分:2)
从它的外观来看,你可以用try/catch
包裹if (!_Cancelled) { ... }
。目前你拥有它的方式(从你提供的代码),你没有在任何地方使用_Cancelled
。新代码如下:
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;
}
}
if (!_Cancelled) {
// execute
Exception _Error = null;
try
{
Proxy.CoreService.DeleteSnapshot(documentId);
LoadSnapshots(null);
}
catch (Exception ex) { _Error = ex; }
}
// 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();
}
}
}
答案 4 :(得分:2)
为什么不在GOTO和标签之间的那些线周围if (!_Cancelled)
?
答案 5 :(得分:1)
一般来说: 相反,重构代码将更加清晰和可维护,因此不需要goto。这是一个很大的方法,应该分解一下。
偶尔goto是一个不错的选择,但很多时候,当简单的重构就足够了时,它会被使用。
在你的情况下: 在你的情况下,它似乎从很多其他答案建议使用取消的标志将解决你的问题没有goto。
答案 6 :(得分:1)
尝试用此包装删除快照并删除GOTO
和END
标签
if(!_Cancelled)
{
Exception _Error = null;
try
{
Proxy.CoreService.DeleteSnapshot(documentId);
LoadSnapshots(null);
}
catch (Exception ex) { _Error = ex; }
}
答案 7 :(得分:0)
只需在if语句中使用已取消的变量,看看是否应该跳过剩下的代码。
答案 8 :(得分:0)
您的代码中不需要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;
}
}
if (!_Cancelled) {
// execute
Exception _Error = null;
try
{
Proxy.CoreService.DeleteSnapshot(documentId);
LoadSnapshots(null);
}
catch (Exception ex) { _Error = ex; }
}
// 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();
}
}
}
答案 9 :(得分:0)
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;
}
}
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;
});
// 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();
}
}
}
答案 10 :(得分:-1)
因为一个开关......休息可以让工作更干净。
您首先将CancleArgs声明为枚举{...已取消,...,END}
switch (CancleArgs) { case Canceled: _Cancelled = true; break; ... other stuff case END: { // complete if (DeleteSnapshotCompleted != null) { AsyncCompletedEventArgs _CompleteArgs = new AsyncCompletedEventArgs(_Error, _Cancelled, null); DeleteSnapshotCompleted(this, _CompleteArgs); } // bubble error if (_Error != null) throw _Error; } break; } // run it ...
没有重构,因为它应该以这种方式开始编写。 ;)