看来,OP的目的是寻找一个解决他的问题并解决他当时正在努力解决的当前问题的良好模式。
OP:“我可以将每个计算都包装在一个辅助方法中,该方法在失败时返回null,然后只使用??
运算符,但是有一种更通用的方法(即,不必为我想要的每个方法编写辅助方法)我曾经考虑过使用泛型编写一个静态方法,该方法将任何给定的方法包装在try / catch中,并在失败时返回null,但是我不确定该如何处理。有什么想法吗?”
我看到了很多很好的模式,这些模式避免了嵌套在该提要中的try try catch块,但是没有找到解决上面提到的问题的方法。所以,这是解决方案:
如前所述,他想制作一个包装对象,该null
对象将在failure时返回。我将其称为pod(异常安全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
S和ReferenceTypeResult
S)是足够的。
这是的代码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;
}
}
这就是您可以利用空值促销运算符??
与一流公民实体(delegate
s)的功能相结合的方式。