Sepertinya niat OP adalah mencari pola yang baik untuk menyelesaikan masalahnya dan menyelesaikan masalah yang saat ini sedang ia geluti.
OP: "Saya bisa membungkus setiap kalkulasi dalam metode helper yang mengembalikan nol pada kegagalan, dan kemudian hanya menggunakan ??
operator, tetapi adakah cara untuk melakukan ini secara lebih umum (yaitu tanpa harus menulis metode pembantu untuk setiap metode yang saya inginkan menggunakan)? Saya telah berpikir tentang menulis metode statis menggunakan obat generik yang membungkus metode tertentu dalam mencoba / menangkap dan mengembalikan nol pada kegagalan, tetapi saya tidak yakin bagaimana saya akan melakukannya. Ada ide? "
Saya melihat banyak pola bagus yang menghindari blok tangkap percobaan bersarang , yang diposting di umpan ini, tetapi tidak menemukan solusi untuk masalah yang dikutip di atas. Jadi, inilah solusinya:
Seperti yang disebutkan OP di atas, dia ingin membuat objek pembungkus yang mengembalikan null
kegagalan . Saya akan menyebutnya pod ( Pod yang aman untuk pengecualian ).
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;
Tetapi bagaimana jika Anda ingin membuat pod yang aman untuk hasil Jenis Referensi yang dikembalikan oleh fungsi / metode 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}";
}
Jadi, Anda mungkin memperhatikan bahwa tidak perlu "menulis metode pembantu untuk setiap metode yang ingin Anda gunakan" .
The dua jenis polong (untuk ValueTypeResult
s dan ReferenceTypeResult
s) yang cukup .
Ini kodenya SafePod
. Ini bukan wadah. Sebaliknya, ini membuat pembungkus delegasi yang aman untuk pengecualian untuk ValueTypeResult
s dan ReferenceTypeResult
s.
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;
}
}
Begitulah cara Anda dapat memanfaatkan operator penggabungan nol yang ??
dikombinasikan dengan kekuatan entitas warga negara kelas satudelegate
.