try-catch代码的每一行代码都没有单独的try-catch块(Try-catch every

2019-06-26 15:12发布

我目前没有这个问题 ,但你永远不知道,而思想实验总是很有趣。

忽略了你就必须与你的架构,甚至可以尝试这个明显的问题 ,让我们假设你有别人的设计的一些可怕编写的代码,你需要做的一堆广泛和多样的操作都必须在相同的代码块,如:

WidgetMaker.SetAlignment(57);
contactForm["Title"] = txtTitle.Text;
Casserole.Season(true, false);
((RecordKeeper)Session["CasseroleTracker"]).Seasoned = true;

由百相乘。 其中的一些可能会奏效,其他人可能会去严重错误。 你需要的是C#相当于“在错误恢复下一个”的,否则你会最终复制和粘贴周围的代码行数试试渔获物。

你如何试图解决这个问题?

Answer 1:

这是很明显,你会写在VB.NET代码,实际上确有错误时继续下一步 ,并将其导出一个DLL到C#。 否则就是摆明了处罚馋嘴。



Answer 2:

public delegate void VoidDelegate();

public static class Utils
{
  public static void Try(VoidDelegate v) {
    try {
      v();
    }
    catch {}
  }
}

Utils.Try( () => WidgetMaker.SetAlignment(57) );
Utils.Try( () => contactForm["Title"] = txtTitle.Text );
Utils.Try( () => Casserole.Season(true, false) );
Utils.Try( () => ((RecordKeeper)Session["CasseroleTracker"]).Seasoned = true );


Answer 3:

重构为个人,以及命名方法:

AdjustFormWidgets();
SetContactTitle(txtTitle.Text);
SeasonCasserole();

每个市场都要受到适当的保护。



Answer 4:

我会说什么也不做

没错这就是正确的,什么也不做。

你有明确的两件事情对我说:

  1. 你知道的架构是borked。
  2. 有一吨这样的废话。

我说:

  • 没做什么。
  • 添加一个全局错误处理程序每​​次去繁荣时向您发送电子邮件。
  • 等到东西倒了(或未能通过测试)
  • 更正(重构的页面的范围内,根据需要)。
  • 每次重复发生问题的时间。

您将有此清理了在任何时间,如果它是坏的。 是的,我知道这听起来很苏茨基,你可能会出拉你的头发以及补丁来开始的,但它可以让你的代码,实际上是工作无论多么糟糕的(大)量之前解决贫困/ bug的代码它看起来。

一旦你开始赢得这场战争,你将有代码更好地处理(由于所有的重构),你将不得不为它的获胜设计一个更好的主意..

试图总结这一切在泡沫包装可能会花一长做,你仍然不会有任何接近固定的问题。



Answer 5:

快速失败

为了详细说明,我想我质疑的问题。 如果抛出一个异常,为什么你想你的代码简单地继续,好像什么都没有发生? 要么你希望在某些情况下例外,在这种情况下,你写一个try-catch块周围的代码,进行处理,或有一个意外的错误,在这种情况下,你应该更喜欢你的应用程序的中止或重试,或失败。 没有进行像一个受伤的僵尸呻吟的“大脑”。



Answer 6:

这是一件事,有一个预处理是有用的。 您可以定义燕子例外宏,然后用一个快速的脚本,宏添加到所有行。

所以,如果这是C ++,你可以这样做:

#define ATTEMPT(x) try { x; } catch (...) { }
// ...
ATTEMPT(WidgetMaker.SetAlignment(57));
ATTEMPT(contactForm["Title"] = txtTitle.Text);
ATTEMPT(Casserole.Season(true, false));
ATTEMPT(((RecordKeeper)Session["CasseroleTracker"]).Seasoned = true);

不幸的是,没有多少语言似乎包括像C / C ++做了预处理。

你可以创建自己的预处理器,并将其添加为预生成的一步。 如果你觉得完全自动化它,你也许可以写一个预处理,将采取实际的代码文件,并在添加try / catch语句的东西在自己的(这样你就不必块手动添加这些尝试()的代码) 。 确保它只是修改它应该是很困难的,虽然线(必须跳过变量声明,循环结构等,以你不打破建立)。

不过,我认为这是一个可怕的想法,绝不应该做的,但问题是问。 :)

真的,你不应该永远做到这一点。 你需要找到什么导致这个错误并改正它。 吞咽/忽略错误是一件坏事做的,所以我觉得这里的正确答案是“修正错误,不用管它!”。 :)



Answer 7:

On Error Resume Next是在C#世界一个非常糟糕的主意。 也不会增加相当于On Error Resume Next实际上可以帮助你。 所有这将要做的就是让你在一个糟糕的状态,这可能导致更多微妙的错误,数据丢失和可能的数据损坏。

但给提问者自己因,你可以添加一个全球性的处理,并检查TargetSite,看看哪些方法borked。 然后,你至少可以知道它borked在哪一行。 接下来的部分将试图找出如何设置“下一条语句”以同样的方式在调试器做的。 希望您的堆栈将不会在这一点上展开,也可以重新创建它,但它肯定是值得一试。 然而,由于这种方法的代码必须在调试模式下,每次运行,这样你就必须包括在您的调试符号。



Answer 8:

正如有人所说,VB允许这样做。 如何做它在C#中以同样的方式? 输入信赖的反射器:

这个:

Sub Main()
    On Error Resume Next

    Dim i As Integer = 0

    Dim y As Integer = CInt(5 / i)


End Sub

翻译成这样:

public static void Main()
{
    // This item is obfuscated and can not be translated.
    int VB$ResumeTarget;
    try
    {
        int VB$CurrentStatement;
    Label_0001:
        ProjectData.ClearProjectError();
        int VB$ActiveHandler = -2;
    Label_0009:
        VB$CurrentStatement = 2;
        int i = 0;
    Label_000E:
        VB$CurrentStatement = 3;
        int y = (int) Math.Round((double) (5.0 / ((double) i)));
        goto Label_008F;
    Label_0029:
        VB$ResumeTarget = 0;
        switch ((VB$ResumeTarget + 1))
        {
            case 1:
                goto Label_0001;

            case 2:
                goto Label_0009;

            case 3:
                goto Label_000E;

            case 4:
                goto Label_008F;

            default:
                goto Label_0084;
        }
    Label_0049:
        VB$ResumeTarget = VB$CurrentStatement;
        switch (((VB$ActiveHandler > -2) ? VB$ActiveHandler : 1))
        {
            case 0:
                goto Label_0084;

            case 1:
                goto Label_0029;
        }
    }
    catch (object obj1) when (?)
    {
        ProjectData.SetProjectError((Exception) obj1);
        goto Label_0049;
    }
Label_0084:
    throw ProjectData.CreateProjectError(-2146828237);
Label_008F:
    if (VB$ResumeTarget != 0)
    {
        ProjectData.ClearProjectError();
    }
}


Answer 9:

重写代码。 试着找集的语句的逻辑上互相依赖,因此,如果一个失败,那么接下来那些毫无意义,并分群赶走到他们自己的函数,并把尝试渔获物一轮他们,如果你想忽略的结果这一点,继续。



Answer 10:

这可以帮助你在identifing有问题最多的部分。

@ JB王谢谢你提醒我。 日志记录应用程序块具有可用于跟踪事件检测事件,你可以找到在MS企业库文档的详细信息。

Using (New InstEvent)
<series of statements> 
End Using

所有在此使用的步骤将被追踪到一个日志文件,您可以分析出来,看看那里的日志中断(如被抛出)和id高的罪犯。

重构是真的是你最好的选择,但如果你有很多,这可以帮助你找出最严重的罪犯。



Answer 11:

可以使用goto语句,但它仍然是混乱的。

我其实是想一种单个语句的try-catch的一段时间。 这将是在某些情况下有益的,如添加日志代码或东西,你不想,如果它不能中断主程序流程。

我怀疑的东西可以用一些与LINQ相关的功能来完成,但真的没有时间去考虑它的时刻。 如果你能找到一个方法来包装一个语句作为一个匿名函数,然后用另外一个来调用一个try-catch块内,它的工作...但不知道这是可能的,只是还没有。



Answer 12:

如果你可以让编译器给你一个表达式树的代码,那么你可以用它包装的原始语句的新try-catch块替换每个语句修改表达式树。 这不是牵强,因为它的声音; 对LINQ,C#获取捕捉lambda表达式作为表达式树可以在用户代码在运行时被操作的能力。

这种做法现在是不可能的.NET 3.5 - 如果没有其他原因,而不是缺乏System.Linq.Expressions一个“尝试”语句。 然而,这很可能是可行的在C#的未来版本一旦DLR和LINQ表达式树的合并完成。



Answer 13:

为什么不使用C#中的写照吗? 您可以创建的代码和使用线#分别为暗示了要放什么东西在每个单独的try / catch块反映一类。 这有几个优点:

  1. 它的略少丑,因为它并不真正需要你裂伤你的源代码,你可以在调试模式下只使用它。
  2. 你学到一些有趣的关于C#,同时实施它。

然而,我会建议对任何这一点,当然,除非你正在接管someelses工作的维护与你需要得到一个手柄上的异常,所以你可以解决这些问题。 可能是有趣的,虽然写的。



Answer 14:

有趣的问题; 非常可怕的。

这会是很好,如果你可以使用宏。 但是,这是抨击C#,所以你可能有一些预处理工作或一些外部工具解决它来包装在个别的try-catch块你行。 不知道你的意思,你不想手动包起来,或者你想完全避免的try-catch。

与此乱搞,我想每一个标记线和跳跃从一个单一的抓回来,没有多少运气。 然而, 克里斯托弗发现正确的方式做到这一点 。 这里也有一些这样的点网的思考有趣的附加讨论和迈克失速的.NET博客 。

编辑:当然。 try-catch / switch-goto上市的解决方案将不实际编译自try标签外的范围, catch 任何人都知道缺少了什么做出这样的编译?

你可以用编译器前处理工序自动化这个也许砍了迈克失速的内联IL工具注入一些错误的无知。

( 猎户座阿德里安的关于检查异常的答案 ,并试图设置下一个指令是有趣了。)

总而言之,这似乎是一个有趣又有益的锻炼。 当然,你必须在什么时候,以决定下一个模拟ON ERROR RESUME胜过努力修复代码的努力。 :-)



Answer 15:

赶在错误UnhandledException事件的应用程序。 这样一来,未处理execptions甚至可以记录为发件人和任何开发商将合理的其他信息。



Answer 16:

不幸的是,你可能是出于运气。 在错误继续下一步是一般严重阻碍了其传统的选项,并且不具有等同的,据我所知在C#。

我会建议留在VB代码(,这听起来就像是给定的来源你的的OnError ResumeNext具体要求),并用或从C#DLL或EXE实现任何你需要的新代码的接口。 然后瓶坯重构造成的代码是安全的,而这种安全的代码,你这样做转换为C#。



Answer 17:

你可以看一下企业库的异常处理组件整合为如何处理未处理的异常一个想法。

如果这是ASP.Net应用程序,还有在Global.asax一个函数调用“的Application_Error”被调用在大多数情况下灾难性故障是另一种情况通常。



Answer 18:

忽略你想避免这样做的所有原因.......

如果它只是一个需要不断线#下来,你可以尝试这样的:

int totalMethodCount = xxx;
for(int counter = 0; counter < totalMethodCount; counter++) {
    try {
        if (counter == 0) WidgetMaker.SetAlignment(57);
        if (counter == 1) contactForm["Title"] = txtTitle.Text;
        if (counter == 2) Casserole.Season(true, false);
        if (counter == 3) ((RecordKeeper)Session["CasseroleTracker"]).Seasoned = true;
    } catch (Exception ex) {
        // log here
    }
}

但是,你必须保持眼睛上的变量范围,如果你尝试重用任何呼叫的结果。



Answer 19:

HILITE每一行,一次一个,“环绕以” try / catch语句。 这避免了你所提到的复制粘贴



文章来源: Try-catch every line of code without individual try-catch blocks