Pergunta

eu atualmente não tem esse problema , mas nunca se sabe, e pensei experiências são sempre divertido.

Ignorando os problemas óbvios que você teria que ter com a sua arquitetura para ainda estar tentando este , vamos supor que você teve algum código horrivelmente escrito de outra pessoa design, e você precisava fazer um grupo de ampla e variada operações no mesmo bloco de código, por exemplo:

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

multiplicada por cem. Alguns destes trabalho poder, outros podem ir muito mal. O que você precisa é o C # equivalente a "na Error Resume Next", caso contrário, você vai acabar copiando e colando try-capturas em torno das muitas linhas de código.

Como você tentar resolver este problema?

Foi útil?

Solução

É bastante óbvio que você ia escrever o código em VB.NET, que na verdade tem On Error Resume Próxima , e exportá-lo em uma DLL de C #. Qualquer outra coisa é apenas ser um glutão para a punição.

Outras dicas

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

Refactor em, métodos bem-nomeados individuais:

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

Cada uma dessas é protegido apropriadamente.

Eu diria nada .

Sim isso é direito, não fazer nada.

Você identificaram claramente duas coisas para mim:

  1. Você sabe que a arquitetura é borked.
  2. Há uma tonelada de essa porcaria.

Eu digo:

  • Não faça nada.
  • Adicionar um manipulador de erro global para lhe enviar um e-mail cada vez que ele faz boom.
  • Aguarde até que algo cai sobre (ou falha em um teste)
  • Corrigir essa (Refactoring conforme necessário no âmbito da página ).
  • Repita cada vez que ocorre um problema.

Você terá esse esclarecido em nenhum momento se é tão ruim assim. Sim, eu sei que soa sucky e você pode estar puxando seu cabelo para fora com correções de bugs para começar, mas vai permitir que você corrigir o código necessitados / Buggy antes a quantidade (grande) de Código que pode realmente estar trabalhando não importa quão horrível que parece.

Uma vez que você começar a ganhar a guerra, você terá um melhor controle sobre o código (devido a todo o seu refactoring), você terá uma idéia melhor para um projeto vencedor para ele ..

tentando envolver tudo isso em plástico bolha é provavelmente vai levar apenas um tempo para fazer e você ainda não estará mais perto de corrigir os problemas.

falhar rapidamente

Para elaborar, eu acho que eu estou questionando a questão. Se uma exceção é lançada, por que você quer que seu código para simplesmente continuar como se nada tivesse acontecido? Ou você espera exceções em determinadas situações, caso em que você escreve um bloco try-catch em torno desse código e lidar com eles, ou se houver um erro inesperado, caso em que você deve preferir o seu pedido para anular ou repetir, ou falhar. Não continua como um gemido zumbi ferido 'cérebros'.

Esta é uma das coisas que ter um pré-processador é útil para. Você pode definir uma macro que engole exceções, em seguida, com um add rápida script que macro para todas as linhas.

Então, se isso fosse C ++, você poderia fazer algo parecido com isto:

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

Infelizmente, não muitas línguas parecem incluir um pré-processador como C / C ++ fez.

Você pode criar seu próprio pré-processador e adicioná-lo como uma etapa de pré-compilação. Se você se sentiu como automatizar completamente você provavelmente poderia escrever um pré-processador que levaria o arquivo de código atual e adicione o material try / catch em em sua própria (para que você não tem que adicionar os TENTATIVA () blocos para o código manualmente) . Certificar-se de que só modificou as linhas que é suposto pode ser difícil embora (tem que saltar declarações de variáveis, construções de laço, etc para que você não quebrar a construir).

No entanto, penso que estes são ideias horríveis e nunca deve ser feito, mas a pergunta foi feita. :)

Realmente, você não deve nunca fazer isso. Você precisa descobrir o que está causando o erro e corrigi-lo. Engolir / erros ignorando é uma coisa ruim para fazer, então eu acho que o correta resposta aqui é "Corrigir o erro, não ignorá-lo!". :)

On Error Resume Next é uma péssima idéia no mundo do C #. Nem adicionando o equivalente a On Error Resume Next realmente ajudá-lo. Tudo o que fazer é deixá-lo em um estado ruim que poderia causar erros mais sutis, perda de dados e, possivelmente, corrupção de dados.

Mas para dar o entrevistador lhe é devido, você pode adicionar um manipulador global e verificar o TargetSite para ver qual método borked. Então você poderia, pelo menos, saber o que alinhá-lo borked diante. A parte seguinte seria a de tentar descobrir como definir a "próxima declaração" da mesma forma que o depurador faz isso. Esperemos que a sua pilha não terá desenrolado neste momento ou você pode recriá-lo, mas é certamente um tiro pena. No entanto, dada esta abordagem o código teria que executar no modo de depuração de cada vez para que você teria seus símbolos de depuração incluído.

Como alguém mencionou, VB permite isso. Como cerca de fazê-lo da mesma forma em C #? Digite refletor fiel:

Este:

Sub Main()
    On Error Resume Next

    Dim i As Integer = 0

    Dim y As Integer = CInt(5 / i)


End Sub

traduz isso:

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

reescrever o código. Tente encontrar conjuntos de declarações que dependem logicamente uns sobre os outros, de modo que se um falhar, em seguida, os próximos não fazem sentido, e colmeia-los em suas próprias funções e colocar try-capturas cercá-los, se você deseja ignorar o resultado de isso e continuar.

Isto pode ajudá-lo na identificando as peças que têm mais problemas.

@ JB Rei Obrigado por me lembrar. O bloco de aplicativo de registro tem um evento de Instrumentação, que pode ser usado para rastrear eventos, você pode encontrar mais informações sobre os documentos da biblioteca MS Enterprise.

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

Todas as etapas deste usando vai ser atribuída a um arquivo de log, e você pode analisar isso para ver onde as quebras de log (ex é jogado) e id os altos infratores.

A refatoração é realmente a sua melhor aposta, mas se você tem um monte, isso pode ajudar a identificar os piores criminosos.

Você poderia usar goto, mas ainda é confuso.

Eu realmente queria um tipo de instrução try-catch solteiro por um tempo. Seria útil em certos casos, como a adição de código de log ou algo que você não quer interromper o fluxo de programa principal se ele falhar.

Eu suspeito algo poderia ser feito com algumas das características associadas com o LINQ, mas realmente não tem tempo para olhar para ele no momento. Se você pudesse encontrar uma maneira de quebrar uma declaração como uma função anônima, em seguida, usar um outro para chamar isso de dentro de um bloco try-catch ele iria trabalhar ... mas não tenho certeza se isso é possível ainda.

Se você pode obter o compilador para dar-lhe uma árvore de expressão para este código, então você pode modificar essa árvore expressão, substituindo cada declaração com um novo bloco try-catch que envolve a declaração original. Isto não é tão absurda quanto parece; para LINQ, C # adquiriu a capacidade de expressões lambda captura como árvores de expressão que podem ser manipulados no código do usuário em tempo de execução.

Esta abordagem não é possível hoje com .NET 3.5 - se não por outra razão que a falta de um "tentar" declaração em System.Linq.Expressions. No entanto, pode muito bem ser viável em uma futura versão do C # uma vez que a fusão das árvores de expressão DLR e LINQ está completa.

Por que não usar o reflexo no c #? Você poderia criar uma classe que reflete sobre os #s código de linha e usar como dica para o que colocar em cada bloco try / catch individual. Isto tem algumas vantagens:

  1. O seu um pouco menos feio como ele realmente não necessitar mangle seu código-fonte e você pode usá-lo apenas durante os modos de depuração.
  2. Você aprende algo interessante sobre c #, enquanto a sua aplicação.

No entanto eu recomendaria contra nada disso, a não ser é claro que você está assumindo o maintance de someelses trabalho e que você precisa para obter uma alça sobre as exceções que você possa corrigi-los. Pode ser divertido para escrever embora.

questão Fun; muito terrível.

Seria bom se você pudesse usar uma macro. Mas isso é soprado C #, de modo que você pode resolvê-lo com algum trabalho de pré-processamento ou alguma ferramenta externa para embrulhar as suas linhas em blocos try-catch individuais. Não tenho certeza se você significava que você não queria manualmente envolvê-los ou que você queria evitar try-catch inteiramente .

Brincando com isso, eu tentei rotular cada linha e salto para trás de uma única captura, sem muita sorte. No entanto, descobriu a correta maneira de fazer isso . Há alguma interessante discussão adicional deste em Dot Net Pensamentos e em Mike Stall .NET Blog .

EDIT: Claro. A solução try-catch / switch-goto listados realmente não vai compilar uma vez que os rótulos try estão fora do escopo em catch. Alguém sabe o que está faltando para fazer algo assim compilação?

Você pode automatizar isso com um passo compilador pré-processar ou talvez cortar-se Mike Stall ferramenta inline IL para injetar algum erro de ignorância.

Orion Adrian resposta sobre examinar a exceção e tentar definir a próxima instrução é interessante.)

Em suma, parece que um exercício interessante e instrutivo. Claro, você tem que decidir em que ponto o esforço para simular ON Error Resume PRÓXIMO supera o esforço para corrigir o código. : -)

Pegue os erros na UnhandledException Evento da aplicação. Dessa forma, execptions não tratadas podem até mesmo ser registrado como para o remetente e quaisquer outras informações que o desenvolvedor seria razoável.

Infelizmente você está provavelmente fora da sorte. No Error Resume Em seguida é uma opção de legado, que geralmente é fortemente desencorajada, e não tem um equivalente para o meu conhecimento em C #.

Eu recomendaria deixando o código em VB (Parece que era a fonte, dado o seu pedido específico de OnError ResumeNext) e interface com ou de um C # dll ou exe que implementa qualquer que seja novo código que você precisa. Então refatoração pré-forma para fazer com que o código para ser seguro, e converter este código seguro para C # como você faz isso.

Você pode olhar para integrar componentes de manipulação de exceção da Enterprise Library para uma ideia de como lidar com exceções não tratadas.

Se isto é para aplicações ASP.NET, há uma função no Global.asax chamado "Application_Error" que é chamada na maioria dos casos com falha catastrófica sendo o outro caso, normalmente.

Ignorando todas as razões que você gostaria de evitar fazer isso .......

Se fosse simplesmente uma necessidade de manter # de linhas para baixo, você poderia tentar algo como:

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

No entanto, você tem que manter um olho sobre o escopo de variáveis ??se você tentar reutilizar qualquer um dos resultados das chamadas.

Hilite cada linha, um de cada vez, 'Surround com' try / catch. Isso evita a copiar colar que você mencionou

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top