OPの意図は、彼の問題を解決し、彼がその時点で苦労していた現在の問題を解決するための良いパターンを見つけることであったようです。
OP:「失敗したときにnullを返すヘルパーメソッドで各計算をラップし、??
演算子を使用することもできますが、これをより一般的に行う方法があります(つまり、目的の各メソッドのヘルパーメソッドを記述する必要はありません。 use)?try / catchで特定のメソッドをラップし、失敗するとnullを返すジェネリックを使用して静的メソッドを書くことを考えましたが、これについてどうすればよいかわかりません。
このフィードに投稿された入れ子になったtry catchブロックを回避する良いパターンがたくさんありましたが、上記の問題の解決策は見つかりませんでした。だから、ここに解決策があります:
上記のOPのように、彼は失敗時に戻るnull
ラッパーオブジェクトを作成したいと考えていました。私はそれをポッド(例外セーフポッド)と呼びます。
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}";
}
したがって、「使用するメソッドごとにヘルパーメソッドを記述する必要がない」ことに気付くかもしれません。
ポッドの2種類(のためのValueTypeResult
SとReferenceTypeResult
S)がある十分。
これがのコードですSafePod
。ただし、コンテナではありません。代わりに、との両方に例外セーフなデリゲートラッパーを作成します。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)の能力と組み合わせて活用できます。