ดูเหมือนว่าความตั้งใจของ OP คือการค้นหารูปแบบที่ดีในการแก้ปัญหาของเขาและแก้ไขปัญหาปัจจุบันที่เขากำลังดิ้นรนอยู่ในขณะนั้น
OP: "ฉันสามารถรวมการคำนวณแต่ละรายการด้วยวิธีตัวช่วยซึ่งส่งคืนค่าว่างเมื่อเกิดความล้มเหลวจากนั้นใช้ตัว??
ดำเนินการ แต่มีวิธีการทำเช่นนี้โดยทั่วไปหรือไม่ (กล่าวคือโดยไม่ต้องเขียนวิธีการช่วยเหลือสำหรับแต่ละวิธีที่ฉันต้องการ ใช้)? ฉันเคยคิดเกี่ยวกับการเขียนวิธีการคงที่โดยใช้ยาสามัญซึ่งรวมวิธีการใด ๆ ในการลอง / จับและส่งคืนค่าว่างเมื่อเกิดความล้มเหลว แต่ฉันไม่แน่ใจว่าจะทำอย่างไรกับสิ่งนี้มีความคิดอย่างไร "
ฉันเห็นรูปแบบที่ดีมากมายที่หลีกเลี่ยงการลองจับบล็อกที่ซ้อนกันโพสต์ในฟีดนี้ แต่ไม่พบวิธีแก้ปัญหาที่อ้างถึงข้างต้น ดังนั้นนี่คือวิธีแก้ปัญหา:
ในฐานะที่เป็น OP กล่าวเขาต้องการที่จะทำให้วัตถุที่ห่อหุ้มซึ่งผลตอบแทนnull
ในความล้มเหลว ฉันจะเรียกมันว่าพ็อด ( 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
s) มีความเพียงพอ
นี่คือรหัสของSafePod
. มันไม่ใช่ภาชนะ แต่จะสร้างกระดาษห่อผู้ร่วมประชุมที่ปลอดภัยเป็นพิเศษสำหรับทั้งValueTypeResult
s และ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;
}
}
นั่นคือวิธีที่คุณสามารถใช้ประโยชน์จากตัวดำเนินการที่??
รวมกันเป็นโมฆะรวมกับพลังของเอนทิตีพลเมืองชั้นdelegate
หนึ่ง