문제

이 질문은 후속 조치입니다 방법이 실패했음을 나타내는 방법. xxx () tryxxx () 패턴은 많은 라이브러리에서 매우 유용 할 수있는 것입니다. 코드를 복제하지 않고 두 구현을 제공하는 가장 좋은 방법이 무엇인지 궁금합니다.

가장 좋은 점 :

public int DoSomething(string a)
{
     // might throw an exception
}
public bool TrySomething(string a, out result)
{
    try
    {
        result = DoSomething(a)
        return true;
    }
    catch (Exception)
    {
        return false;
    }

또는

public int DoSomething(string a)
{
     int result;
     if (TrySomething(a, out result))
     {
         return result;
     }
     else
     {
         throw Exception(); // which exception?
     }
}
public bool TrySomething(string a, out result)
{
    //...
}

본능적으로 첫 번째 예제가 더 정확하다고 생각하지만 (정확히 어떤 예외가 발생했는지 알고 있습니다) 시도/캐치가 너무 비싸지 않습니까? 두 번째 예에서 예외를 포착 할 수있는 방법이 있습니까?

도움이 되었습니까?

해결책

트리 솜이 단지 잡히고 예외를 삼키는 것은 정말 나쁜 생각입니다. tryxxx 패턴의 절반은 예외의 성능을 피하는 것입니다.

예외에서 많은 정보가 필요하지 않은 경우, dosomething 방법이 트리 솜을 호출하고 실패하면 예외를 던질 수 있습니다. 예외에 세부 사항이 필요한 경우 더 정교한 것이 필요할 수 있습니다. 예외의 성능 히트가 어디에 있는지 시간을 정하지 않았다. 만약 그것이 생성보다는 던지기라면 트리 솜과 비슷한 서명을 가진 개인 메소드를 쓸 수 있지만 예외 또는 null을 반환했다.

public int DoSomething(string input)
{
    int ret;
    Exception exception = DoSomethingImpl(input, out ret);
    if (exception != null)
    {
        // Note that you'll lose stack trace accuracy here
        throw exception;
    }
    return ret;
}

public bool TrySomething(string input, out int ret)
{
    Exception exception = DoSomethingImpl(input, out ret);
    return exception == null;
}

private Exception DoSomethingImpl(string input, out int ret)
{
    ret = 0;
    if (input != "bad")
    {
        ret = 5;
        return null;
    }
    else
    {
        return new ArgumentException("Some details");
    }
}

그래도 당신이 그것을 약속하기 전에 시간을 보내십시오!

다른 팁

나는 보통이 패턴을 사용합니다. 내부 메소드가 어떻게 의미가 있는지 여부에 대한 내부 방법이 어떻게 구현되는지에 따라 다릅니다. 조건부 캐치 블록을 사용해야한다면 약간 불쾌해질 수 있습니다 ...

public object DoSomething(object input){
  return DoSomethingInternal(input, true);
}

public bool TryDoSomething(object input, out object result){
  result = DoSomethingInternal(input, false);
  return result != null;
}

private object DoSomethingInternal(object input, bool throwOnError){
  /* do your work here; only throw if you cannot proceed and throwOnError is true */
}

첫 번째 예는 예외를 포착하고 아무것도하지 않고 거짓으로 반환하는 경우 정확합니다.

트리 솜을 아래에서 보이게 바꿀 수 있습니다.

public bool TrySomething(string a, out result, bool throwException)
{
  try
  {
    // Whatever
  }
  catch
  {
    if(throwException)
    {
      throw;
    }
    else
    {
      return false;
    }
  }

}

public bool TrySomething(string a, out result)
{
  return TrySomething(a, out result, false);
}

그래서 복용량은 모양이 될 것입니다

public int DoSomething(string a)
{
  int result;

  // This will throw the execption or 
  // change to false to not, or don't use the overloaded one.
  TrySomething(a, out result, true) 

  return result;      
}

ThrowException이 대중에게 노출 된 트리 좀을 원하지 않는다면 개인 회원으로 만들 수 있습니다.

예외는 비싸 질 수 있으며 문자열에서 약간의 동정인을 확인하여 던지는 것을 방지 할 수 있습니다. 그것은 당신이하려는 일에 달려 있습니다.

이것이 C#이라고 가정하면 두 번째 예라고 말할 것입니다.

public bool TrySomething(string a, out result)
{
    try
    {
        result = DoSomething(a)
        return true;
    }
    catch (Exception)
    {
        return false;
    }
}

그것은 내장을 모방합니다 int.TryParse(string s, out int result), 그리고 제 생각에는 언어/환경과 일치하는 것이 가장 좋습니다.

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