我目前不具有这种问题, 但你永远不知道,和思想的实验中总是有趣的。

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

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

乘以一百。这些可能的工作,其他人可能会严重错误的。你需要什么是C#当量"上的差错恢复下",否则你就要结束了复印,并粘贴试试-抓住周围的许多行代码。

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

有帮助吗?

解决方案

很明显你在VB.NET中编写代码,实际上有 On Error Resume Next ,并将它在DLL中导出到C#。其他任何东西都只是一个暴食者  惩罚。

其他提示

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 );

重构为具有明确名称的个别方法:

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

每一项都得到适当的保护。

我想说的 什么也不做.

是啊这就是正确的,什么都不做。

你必须清楚地确定了两个事情对我说:

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

我说:

  • 什么都不做。
  • 添加一个全球性的错误处理程序发送的电子邮件每次去的时间。
  • 等到东西落在(或失败测试)
  • 正确的,(重构为必要的 的范围内页).
  • 重复的每一次发生问题。

你会有这样的清理在任何时间,如果它是那么糟糕。是的,我知道这听起来很烂,你可以拉你的头发出错误修正开始,但是它会允许你 解决贫困/车码之前 在(大)量 代码实际上可能是工作 无论如何蹩脚的。

一旦你开始赢得这场战争,你将有更好的把手上的码(由于您的所有重构)你将有一个更好的主意的设计。

试图包裹在泡泡包装是可能会采取的只是一个长做的而你将仍然不会有任何接近固定的问题。

快速失败

详细说明,我想我正在质疑这个问题。如果抛出异常,为什么您希望代码只是继续,好像什么都没发生一样?您可能希望在某些情况下出现异常,在这种情况下,您可以围绕该代码编写try-catch块并处理它们,或者出现意外错误,在这种情况下,您应该更喜欢应用程序中止,重试或失败。不要像受伤的僵尸一样呻吟'大脑'。

这是预处理器有用的事情之一。您可以定义一个吞下异常的宏,然后使用快速脚本将该宏添加到所有行。

所以,如果这是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内容(因此您不必手动将这些ATTEMPT()块添加到代码中) 。确保它只修改了它应该是困难的行(必须跳过变量声明,循环结构等,你不会破坏构建)。

但是,我认为这些都是可怕的想法,永远不应该这样做,但问的是。 :)

真的,你不应该这样做。您需要找到导致错误的原因并进行修复。吞咽/忽略错误是一件坏事,所以我认为正确的答案是“修复错误,不要忽视它!”。 :)

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

但是为了让提问者得到应有的答案,你可以添加一个全局处理程序并检查TargetSite以查看borked的方法。然后你至少可以知道它是什么线。接下来的部分是试图弄清楚如何设置“下一个语句”。与调试器一样。希望你的筹码在这一点上不会被解开,或者你可以重新创造它,但它肯定值得一试。但是,根据这种方法,代码必须每次都以调试模式运行,以便包含调试符号。

正如有人提到的,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();
    }
}

重写代码。尝试找到逻辑上相互依赖的语句集,这样如果一个语句失败,那么下一个语句就没有意义了,如果你想忽略它们的结果,那么将它们放到自己的函数中并将它们放在它们周围。那并继续。

这可以帮助您识别问题最多的部分。

@ JB King 谢谢你提醒我。 Logging应用程序块具有可用于跟踪事件的Instrumentation事件,您可以在MS Enterprise库文档中找到更多信息。

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

此使用中的所有步骤都将追溯到一个日志文件,您可以解析它以查看日志中断的位置(ex被抛出)并识别高级违规者。

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

可以使用goto,但它仍然很混乱。

我实际上想要一段时间的单一语句try-catch。在某些情况下它会很有用,例如添加日志代码或者如果失败则不想中断主程序流。

我怀疑与linq相关的一些功能可以做些什么,但目前还没有时间研究它。如果你可以找到一种方法将一个语句包装成一个匿名函数,那么使用另一个方法在try-catch块中调用它可以工作......但不确定这是否可能。

如果您可以让编译器为此代码提供表达式树,那么您可以通过用包装原始语句的新try-catch块替换每个语句来修改该表达式树。这并不像听起来那么牵强;对于LINQ,C#获得了将lambda表达式捕获为表达式树的能力,这些表达式树可以在运行时在用户代码中进行操作。

这种方法目前在.NET 3.5中是不可能的 - 如果没有其他原因而不是缺少“尝试”的话。 System.Linq.Expressions中的语句。但是,一旦完成DLR和LINQ表达式树的合并,它在未来的C#版本中可能是可行的。

为什么不在c#中使用反射?您可以创建一个反映代码的类,并使用行#s作为每个try / catch块中放置内容的提示。这有一些好处:

  1. 它稍微不那么难看,因为它实际上并不需要破坏你的源代码,你只能在调试模式下使用它。
  2. 在实施时,您了解了有关c#的一些有趣内容。
  3. 但是我建议不要这样做,除非你正在接管某些工作的维护,你需要处理异常,以便你可以修复它们。写作可能会很有趣。

有趣的问题;太可怕了。

如果可以使用宏,那就太好了。但这是对C#的抨击,所以你可以通过一些预处理器工作或一些外部工具来解决它,将你的行包装在单独的try-catch块中。不确定您是否意味着您不想手动包装它们或者您想要完全避免try-catch

搞清楚这一点,我尝试标记每一行并从一个捕获中跳回来,没有太多运气。但是,克里斯托弗发现了正确的这样做的方法。有一些有趣的额外讨论在Dot Net Thought Mike Stall的.NET博客

编辑:当然。列出的 try-catch / switch-goto 解决方案实际上不会编译,因为 try 标签超出范围捉。任何人都知道制作类似这样的内容会缺少什么?

您可以使用编译器预处理步骤自动执行此操作,也可以修改 Mike Stall的Inline IL工具注入了一些错误无知。

Orion Adrian's关于检查异常的答案并尝试设置下一条指令也很有趣。)

总而言之,这似乎是一项有趣且富有启发性的练习。当然,你必须决定在什么时候模拟ON ERROR RESUME NEXT的努力超过了修复代码的努力。 : - )

抓住应用程序的UnhandledException事件。这样,甚至可以将未处理的exec记录为发件人以及开发人员合理的其他信息。

不幸的是,你可能运气不好。 On Error Resume Next是一个遗留选项,通常非常不鼓励,并且与C#中的知识不相同。

我建议将代码保留在VB中(听起来这是源代码,根据您对OnError ResumeNext的特定请求)以及与C#dll或exe接口,以实现您需要的任何新代码。然后执行重构以使代码安全,并在执行此操作时将此安全代码转换为C#。

您可以查看集成企业库的异常处理组件,以了解如何处理未处理的异常。

如果这是针对ASP.Net应用程序的,则Global.asax中有一个名为“Application_Error”的函数。在大多数情况下,通常会发生灾难性故障而被调用。

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

如果只是需要保持行数减少,你可以尝试类似:

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
    }
}

但是,如果您尝试重用任何调用结果,则必须密切关注变量范围。

Hilite每一行,一次一个,'环绕'尝试/捕获。这避免了你提到的复制粘贴

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top