ฉันจะให้ข้อมูลเพิ่มเติมเกี่ยวกับข้อยกเว้นได้อย่างไร


20

ทุกครั้งที่ฉันต้องการให้ข้อมูลเพิ่มเติมเกี่ยวกับข้อยกเว้นที่ฉันสงสัยว่าวิธีใดเป็นวิธีที่ถูกต้องในการทำสิ่งนี้


เพื่อประโยชน์ของคำถามนี้ฉันได้เขียนตัวอย่าง สมมติว่ามีคลาสที่เราต้องการอัพเดตAbbreviationคุณสมบัติ จากมุมมองของโซลิดมันอาจจะไม่สมบูรณ์แบบ แต่แม้ว่าเราจะผ่านวิธีปฏิบัติงานผ่าน DI ด้วยบริการบางอย่างสถานการณ์เดียวกันก็จะเกิดขึ้น - มีข้อยกเว้นเกิดขึ้นและไม่มีบริบทใด ๆ เกิดขึ้น กลับไปที่ตัวอย่าง ...

class Person
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Abbreviation { get; set; }
}

จากนั้นมีอินสแตนซ์ของคลาสและลูปที่เรียกเมธอดของผู้ปฏิบัติงาน StringTooShortExceptionมันสามารถโยน

var persons =
{
    new Person { Id = 1, Name = "Fo" },
    new Person { Id = 2, Name = "Barbaz" },
}

public IEnumerable<Person> GenerateAbbreviation(IEnumerable<Person> persons)
{
    foreach (var person in persons)
    {
        try
        {
            person.Abbreviation = GenerateAbbreviation(person.Name);
        }
        catch(Exception ex)
        {
            // ?
        }
    }
    // throw AggregateException...
}

public IEnumerable<string> GenerateAbbreviation(string value)
{
    if (value.Length < 5)
    {
        throw new StringTooShortException(value);
    }

    // generate abbreviation
}

คำถามคือ: วิธีการเพิ่มPersonหรือId(หรือสิ่งอื่นใด)?


ฉันรู้สามเทคนิคต่อไปนี้:


1 - ใช้Dataคุณสมบัติ

ข้อดี:

  • ง่ายต่อการตั้งค่าข้อมูลเพิ่มเติม
  • ไม่ต้องการการสร้างข้อยกเว้นเพิ่มเติม
  • ไม่ต้องการเพิ่มเติม try/catch

จุดด้อย:

  • ไม่สามารถรวมเข้ากับ Message
  • คนตัดไม้เพิกเฉยฟิลด์นี้และจะไม่ทิ้งมัน
  • ต้องใช้กุญแจและหล่อค่าได้เพราะ object
  • ไม่เปลี่ยนรูป

ตัวอย่าง:

public IEnumerable<Person> GenerateAbbreviation(IEnumerable<Person> persons)
{
    foreach (var person in persons)
    {
        try
        {
            person.Abbreviation = GenerateAbbreviation(person.Name);
        }
        catch(Exception ex)
        {
            ex.Data["PersonId"] = person.Id;
            // collect ex
        }
    }
    // throw AggregateException...
}

2 - ใช้คุณสมบัติที่กำหนดเอง

ข้อดี:

  • คล้ายกับDataคุณสมบัติ แต่พิมพ์อย่างมาก
  • ง่ายต่อการรวมเข้ากับ Message

จุดด้อย:

  • ต้องมีข้อยกเว้นที่กำหนดเอง
  • คนตัดไม้จะไม่สนใจพวกเขา
  • ไม่เปลี่ยนรูป

ตัวอย่าง:

public IEnumerable<Person> GenerateAbbreviation(IEnumerable<Person> persons)
{
    foreach (var person in persons)
    {
        try
        {
            person.Abbreviation = GenerateAbbreviation(person.Name);
        }
        catch(Exception ex)
        {
            // not suitable for this exception because 
            // it doesn't have anything in common with the Person
        }
    }
    // throw AggregateException...
}

3 - ตัดข้อยกเว้นด้วยข้อยกเว้นอื่น

ข้อดี:

  • Message สามารถจัดรูปแบบในวิธีที่คาดการณ์ได้
  • คนตัดไม้จะถ่ายโอนข้อยกเว้นภายใน
  • ไม่เปลี่ยนรูป

จุดด้อย:

  • ต้องการเพิ่มเติม try/catch
  • ทำรังซ้อน
  • เพิ่มความลึกของการ exeptions

ตัวอย่าง:

public IEnumerable<Person> GenerateAbbreviation(IEnumerable<Person> persons)
{
    foreach (var person in persons)
    {
        try
        {
            try
            {
                person.Abbreviation = GenerateAbbreviation(person.Name);
            }
            catch(Exception ex)
            {
                throw new InvalidPersonDataException(person.Id, ex);
            }
        }
        catch(Exception ex)
        {
            // collect ex
        }
    }
    // throw AggregateException...
}

  • มีรูปแบบอื่น ๆ อีกไหม?
  • มีรูปแบบที่ดีขึ้นหรือไม่
  • คุณสามารถแนะนำวิธีปฏิบัติที่ดีที่สุดสำหรับพวกเขา / ทุกคน?

ไม่คุ้นเคยกับข้อยกเว้นใน C # แต่โดยปกติฉันคาดหวังว่าอินสแตนซ์ Person ยังคงใช้ได้เมื่อมีการโยนข้อยกเว้น คุณเคยลองไหม
John Kouraklis

1
@JohnKouraklis นี่ไม่ใช่คำถามที่เกี่ยวกับ ;-) มันเป็นเพียงตัวอย่างที่ง่ายมากที่จะแสดงให้เห็นถึงสิ่งที่ฉันหมายถึงโดยข้อมูลเพิ่มเติม ถ้าฉันโพสต์ที่นี่กรอบทั้งหมดซึ่งวิธีการ mutliple สามารถโยนข้อยกเว้นและข้อมูลบริบทระดับ mutliple ควรได้รับไม่มีใครอาจจะอ่านและฉันมีเวลายากมากที่จะอธิบาย
t3chb0t

@JohnKouraklis ฉันเพิ่งสร้างมันขึ้นมาเพื่อการสาธิต
t3chb0t

@ t3chb0t ฉันคิดว่าคุณตอบคำถามของคุณเองที่นี่ ลองพิจารณาการย้าย 1, 2 และ 3 เป็นคำตอบและปรับคำถามของคุณดังนั้นจึงไม่ขอให้ฉันเลือกสไตล์ตามความคิดเห็นของฉัน
candied_orange

เกิดอะไรขึ้นกับข้อยกเว้นที่กำหนดเอง ทำอย่างถูกต้องซึ่งเป็นส่วนหนึ่งของภาษาโดเมนของคุณและช่วยให้คุณได้รับข้อมูลที่เป็นประโยชน์
RubberDuck

คำตอบ:


6

Data FTW

"ตรงกันข้าม" ของคุณ:

  • "ไม่สามารถรวมเข้ากับข้อความได้อย่างง่ายดาย"

-> สำหรับคุณประเภทยกเว้นก็ควรจะเพียงพอที่ง่ายต่อการแทนที่Messageเพื่อที่จะไม่ incorporate Data.. แต่ฉันเท่านั้นที่จะพิจารณาเรื่องนี้ถ้าเป็นข้อความData

  • "คนตัดไม้ไม่สนใจช่องนี้และจะไม่ทิ้ง"

Googling for Nlog เป็นตัวอย่างให้ผลตอบแทน :

ตัวแสดงโครงร่างข้อยกเว้น

( ... )

รูปแบบ - รูปแบบของการส่งออก ต้องเป็นรายการคั่นด้วยเครื่องหมายจุลภาคของคุณสมบัติข้อยกเว้น: Message, Type, ShortType, ToString, Method, และStackTrace Dataค่าพารามิเตอร์นี้ไม่คำนึงถึงขนาดตัวพิมพ์ ค่าเริ่มต้น:message

ดังนั้นดูเหมือนว่าสามารถกำหนดค่าได้ง่าย

  • ต้องใช้คีย์และการหล่อเนื่องจากค่าเป็นวัตถุ

ฮะ? เพียงทิ้งสิ่งของในนั้นและตรวจสอบให้แน่ใจว่าพวกเขามีToString()วิธีการใช้งาน

นอกจากนี้ฉันไม่เห็นปัญหาใด ๆ กับปุ่ม เพียงแค่ใช้เอกลักษณ์ที่ไม่รุนแรงและคุณก็ทำได้ดี


คำเตือน: นี่คือสิ่งที่ฉันสามารถเห็นได้ทันทีจากคำถามและสิ่งที่ฉันไปDataใน 15 นาที ฉันคิดว่ามันมีประโยชน์เล็กน้อยฉันเลยใช้มันเป็นคำตอบ แต่ฉันไม่เคยใช้Dataตัวเองดังนั้นมันอาจเป็นไปได้ว่าผู้ถามที่นี่รู้วิธีนี้มากกว่าฉัน


ฉันได้ข้อสรุปว่ามีเพียงสองสิ่งเกี่ยวกับข้อยกเว้นที่มีประโยชน์คือชื่อและข้อความ ทุกอย่างอื่นเป็นเพียงเสียงไร้ประโยชน์ที่สามารถและควรละเว้นเพราะมันง่ายเกินไปที่จะพึ่งพามัน
t3chb0t

2

ทำไมคุณถึงโยนข้อยกเว้น ที่จะมีพวกเขาจับและจัดการ

โค้ดที่จับได้ทำงานอย่างไรถึงวิธีจัดการกับข้อยกเว้น การใช้คุณสมบัติที่คุณกำหนดไว้บนวัตถุข้อยกเว้น

อย่าใช้คุณสมบัติข้อความเพื่อระบุข้อยกเว้นและไม่ให้ "ข้อมูล" ที่ผู้ดำเนินการที่มีศักยภาพควรเชื่อถือ มันผันผวนเกินไปและไม่น่าเชื่อถือเกินไป

ฉันไม่เคยใช้คุณสมบัติ "Data" มาก่อน แต่มันฟังดูธรรมดาเกินไป

นอกจากว่าคุณจะสร้างคลาสของข้อยกเว้นหลายคลาสแต่ละตัวจะระบุกรณีพิเศษเฉพาะคุณจะรู้ได้อย่างไรว่าคุณได้รับข้อยกเว้น "ข้อมูล" หมายถึงอะไร (ดูความคิดเห็นก่อนหน้าเกี่ยวกับ "ข้อความ")


1
ฉันจะบอกว่าDataไม่มีประโยชน์สำหรับการจัดการ แต่มีประโยชน์สำหรับการบันทึกเพื่อหลีกเลี่ยงMessageการจัดรูปแบบนรก
Martin Ba

-1

ฉันชอบตัวอย่างที่สามของคุณอย่างไรก็ตามมีวิธีอื่นที่สามารถเข้ารหัสเพื่อกำจัด "การต่อต้าน" ส่วนใหญ่ของคุณได้

public IEnumerable<Person> GenerateAbbreviation(IEnumerable<Person> persons)
{
    var exceptions = new List<InvalidPersonDataException>();

    foreach (var person in persons)
    {
        try
        {
            person.Abbreviation = GenerateAbbreviation(person.Name);
        }
        catch(Exception ex)
        {
            exceptions.Add(new InvalidPersonDataException(person.Id, ex));
        }
    }

    if (exceptions.Any())
    {
        throw new AggregateException(exceptions);
    }
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.