문제

그것은 가능한 경우 확인 코드는 현재 실행 중인에서의 컨텍스트 finally 처리기로 결과의 예외를 발생되는?내가 오히려 좋아를 사용하는 IDisposable 패턴을 구현하는 입/출력 범위 지정 기능을,그러나 우려와 함께 이 패턴은 당신이하지 않을 수도 있습니다 원하는 end-of-범위 동작이 발생할 경우 예외가 발생하의 몸에 using.나는 뭔가를 찾고 다음과 같다:

public static class MyClass
{
    public static void MyMethod()
    {
        using (var scope = MyScopedBehavior.Begin())
        {
            //Do stuff with scope here
        }
    }
}

public sealed class MyScopedBehavior : IDisposable
{
    private MyScopedBehavior()
    {
        //Start of scope behavior
    }

    public void Dispose()
    {
        //I only want to execute the following if we're not unwinding
        //through finally due to an exception:
        //...End of scope behavior    
    }

    public static MyScopedBehavior Begin()
    {
        return new MyScopedBehavior();
    }
}

다른 방법이 있다 내가 이것을 달성할 수 있(통과하는 위임하는 기능 둘러싸는 전화로 특정 행위)지만,저는 호기심 가능한 경우에 그것을 할 사용 IDisposable 패턴입니다.


실제로,이것은 분명히 묻고 답하기 전에 .그것은 가능한 가을 감지하는 매우 hackish 종류의 방법입니다.나지 않을 것이 실제로 사용하는 기술이지만,그것은 흥미를 알고 있는 것이 가능합니다.

도움이 되었습니까?

해결책

이를 수행하는이를 수행하는 수단은 추가 방법을 필요로합니다.

public static void MyMethod()
{
    using (var scope = MyScopedBehavior.Begin())
    {
        //Do stuff with scope here
        scope.Complete(); // Tells the scope that it's good
    }
}
.

이렇게하면 범위 객체가 오류로 인해 처분 여부를 추적 할 수 있습니다.이것은 Transactionscope 님이 찍은 접근 방식입니다. TransactionsCope.Complete )을 참조하십시오.

다른 팁

측면으로 점,IL 을 지정할 수 있습니다 SEH fault 블록과 비슷 finally 하지만 입력 예외가 발생하면-예를 볼 수 있습니다 , 약 2/3rds 페이지를 아래로.불행하게도,C#노출하지 않는다는 이 기능이 있습니다.

단위 테스트와 비슷한 것을 찾고있었습니다. 테스트 실행 후에 객체를 정리하는 데 사용하는 도우미 클래스가 있으며 멋진 '사용'구문을 유지하고 싶습니다.또한 테스트가 실패한 경우 정리되지 않는 옵션을 원했습니다.내가 생각해 왔던 것은 marshal.getExceptionCode를 호출하는 것입니다.() .모든 경우에 적합한 지 모르겠지만 테스트 코드의 경우 잘 작동하는 것 같습니다.

제가 올 수있는 최선은 다음과 같습니다 :

using (var scope = MyScopedBehavior.Begin())
{
  try
  {
    //Do stuff with scope here
  }
  catch(Exception)
  {
    scope.Cancel();
    throw;
  }
}
.

물론 scope.Cancel()는 dispose ()

에서 아무 일도 일어나지 않는지 확인합니다.

다음 패턴은 API 오용의 문제점을 피할 수 있습니다. 범위 완료 방법은 I.E.E.E.E.E.E.에 완전히 생략되었거나, 논리적 조건으로 인해 호출되지 않습니다.나는 이것이 당신의 질문에 더 가깝게 대답하고 API 사용자의 코드가 적다는 것 같습니다.

편집

Dan의 코멘트 후에 더 간단합니다.

public class Bling
{
    public static void DoBling()
    {
        MyScopedBehavior.Begin(() =>
        {
            //Do something.
        }) ;
    }   
}

public static class MyScopedBehavior
{
    public static void Begin(Action action)
    {
        try
        {
            action();

            //Do additonal scoped stuff as there is no exception.
        }
        catch (Exception ex)
        {
            //Clean up...
            throw;
        }
    }
}   
.

내가 생각하는 가장 좋은 방법을 사용하여 작성 try/catch/finally 절 수 있습니다.연구 항목에서 첫 번째'효과적인 c#"책입니다.좋은 C#을 해커 정확히 알고 있어야를 사용하여 확장됩니다.그것은 조금 변경되었습니다.Net1.1-수 있습니다 당신은 지금 몇 가지 중 하나를 사용하여 다른.그래서 사용하는 반사체,연구 un-설탕된 코드입니다.

다음을 작성할 때 자신의 코드를 사용하거나 using 또는 당신의 물건입니다.그것은 정말 열심히,그리고 좋은 것은 알고 있습니다.

당신이 얻을 수있는 멋진과는 다른 묘지만,그것은 너무 무거운 느낌,그리고 심지어는 효율적이지 않습니다.나의 코드를 포함 샘플입니다.

게으른 방법:

using (SqlConnection cn = new SqlConnection(connectionString))
using (SqlCommand cm = new SqlCommand(commandString, cn))
{
    cn.Open();
    cm.ExecuteNonQuery();
}

수동 방법:

bool sawMyEx = false;
SqlConnection cn =  null;
SqlCommand cm = null;

try
{
    cn = new SqlConnection(connectionString);
    cm = new SqlCommand(commandString, cn);
    cn.Open();
    cm.ExecuteNonQuery();
}
catch (MyException myEx)
{
    sawMyEx = true; // I better not tell my wife.
    // Do some stuff here maybe?
}
finally
{
    if (sawMyEx)
    {
        // Piss my pants.
    }

    if (null != cm);
    {
        cm.Dispose();
    }
    if (null != cn)
    {
        cn.Dispose();
    }
}

그것은 것(이럴 매우)있다면 도움이들의 변형 IDisposableDispose 방법 허용한 매개 변수를 나타내는 어떤 예외는 경우,보류되었을 때 실행됩니다.다른 것들 중에는 이벤트 Dispose 가를 수행할 수상 정리,그것은 던질 수 있는 예외에 대한 정보를 포함하는 이전 예외는 아니다.그것은 또한 허용 Dispose 방법을 던지는 경우에는 예외가"코드를 잊는"무언가를 하는지에 using 블록을 덮어쓰지 말고 다른 예외를 일으킬 수 있는 사용 블록을 종료 됩니다.불행하게도,이러한 기능으로 존재합니다.

거기에 수많은 기사는 제안의 수단을 사용하여 API 함수는지 여부를 알아보려면 보류 중인 예외를 존재합니다.하나의 중요한 문제로 이러한 접근 방식은 가능하는 코드에서 실행 중일 수 있는 finallytry 는 성공적으로 완료,하지만 될 수 있는 중첩에 finally 그의 블록 try 종료 됩니다.는 경우에도 Dispose 방법을 식별할 수 있는 그런 상황이 존재하고,그것이 알 수 없는 try 블록 그것은"지배"니다.수을 공식화하기거나 상황이 적용됩니다.

그것이 최선의 방법은 아마가 있는 명시 적으로"성공은"방법 및 가정이 실패하는 경우 그것은이라고,그리고 그 결과의 전화를 잊어"성공은"방법을 명백해야 하는 경우에도 예외가 발생합니다.하나는 것이 도움이 될 수 있는 간단한 유틸리티는 방법을 것 같은 뭔가

T Success<T>(T returnValue)
{
  Success();
  return T;
}

따라서 수 있도록 다음과 같은 코드:

return scopeGuard.Success(thingThatMightThrow());

var result = thingThatMightThrow();
scopeGuard.Success();
return result;

왜 그 끝에 try { } 블록 내부에서 단순히 폐기하지 않고 마침내 사용하지 않으셨습니까?이것은 당신이 찾고있는 행동 인 것처럼 보입니다.

이것은 또한 다른 사람들이 수업을 사용할 수 있는지 측면에서보다 현실적으로 보입니다.이제까지 사용하는 모든 사람들이 예외의 경우에 처분하고 싶지 않을 것입니다.또는 클래스의 소비자 가이 동작을 처리해야합니까?

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top