OP의 의도는 자신의 문제를 해결하기위한 좋은 패턴을 찾고 그 순간 그가 고심하고있는 현재 문제를 해결하는 것이었던 것 같습니다.
OP : "각 계산을 실패시 null을 반환하는 도우미 메서드로 래핑 한 다음 ??
연산자를 사용할 수 있지만보다 일반적으로이 작업을 수행하는 방법이 있습니다 (예 : 원하는 각 메서드에 대한 도우미 메서드를 작성하지 않아도 됨). try / catch에서 주어진 메서드를 래핑하고 실패시 null을 반환하는 제네릭을 사용하여 정적 메서드를 작성하는 것에 대해 생각했지만 어떻게해야할지 모르겠습니다. 어떤 아이디어라도 있습니까? "
이 피드에 게시 된 중첩 된 try catch 블록을 피하는 좋은 패턴을 많이 보았지만 위에서 언급 한 문제에 대한 해결책을 찾지 못했습니다. 그래서 여기에 해결책이 있습니다.
OP에서 언급했듯이 그는 실패시 반환null
되는 래퍼 객체를 만들고 싶었습니다 . 나는 그것을 pod ( Exception-safe pod )라고 부를 것입니다.
public static void Run()
{
// The general case
// var safePod1 = SafePod.CreateForValueTypeResult(() => CalcX(5, "abc", obj));
// var safePod2 = SafePod.CreateForValueTypeResult(() => CalcY("abc", obj));
// var safePod3 = SafePod.CreateForValueTypeResult(() => CalcZ());
// If you have parameterless functions/methods, you could simplify it to:
var safePod1 = SafePod.CreateForValueTypeResult(Calc1);
var safePod2 = SafePod.CreateForValueTypeResult(Calc2);
var safePod3 = SafePod.CreateForValueTypeResult(Calc3);
var w = safePod1() ??
safePod2() ??
safePod3() ??
throw new NoCalcsWorkedException(); // I've tested it on C# 7.2
Console.Out.WriteLine($"result = {w}"); // w = 2.000001
}
private static double Calc1() => throw new Exception("Intentionally thrown exception");
private static double Calc2() => 2.000001;
private static double Calc3() => 3.000001;
하지만 CalcN () 함수 / 메소드에서 반환 된 참조 유형 결과에 대한 안전한 포드 를 만들고 싶다면 어떻게해야 합니까?
public static void Run()
{
var safePod1 = SafePod.CreateForReferenceTypeResult(Calc1);
var safePod2 = SafePod.CreateForReferenceTypeResult(Calc2);
var safePod3 = SafePod.CreateForReferenceTypeResult(Calc3);
User w = safePod1() ?? safePod2() ?? safePod3();
if (w == null) throw new NoCalcsWorkedException();
Console.Out.WriteLine($"The user object is {{{w}}}"); // The user object is {Name: Mike}
}
private static User Calc1() => throw new Exception("Intentionally thrown exception");
private static User Calc2() => new User { Name = "Mike" };
private static User Calc3() => new User { Name = "Alex" };
class User
{
public string Name { get; set; }
public override string ToString() => $"{nameof(Name)}: {Name}";
}
따라서 "사용하려는 각 메서드에 대한 도우미 메서드를 작성"할 필요가 없음을 알 수 있습니다 .
포드의 두 가지 유형 (대한 ValueTypeResult
의과 ReferenceTypeResult
들)이다 충분 .
다음은의 코드입니다 SafePod
. 그래도 컨테이너가 아닙니다. 대신 s 및 s 모두에 대해 예외 안전 대리자 래퍼 를 만듭니다 .ValueTypeResult
ReferenceTypeResult
public static class SafePod
{
public static Func<TResult?> CreateForValueTypeResult<TResult>(Func<TResult> jobUnit) where TResult : struct
{
Func<TResult?> wrapperFunc = () =>
{
try { return jobUnit.Invoke(); } catch { return null; }
};
return wrapperFunc;
}
public static Func<TResult> CreateForReferenceTypeResult<TResult>(Func<TResult> jobUnit) where TResult : class
{
Func<TResult> wrapperFunc = () =>
{
try { return jobUnit.Invoke(); } catch { return null; }
};
return wrapperFunc;
}
}
이것이 바로 일류 시민 엔티티 ( s) ??
의 힘과 결합 된 널 통합 연산자를 활용하는 방법 입니다.delegate