.NET: ข้อยกเว้นใดที่ควรทิ้งเมื่อการตั้งค่าคอนฟิกที่จำเป็นขาดหายไป?


123

นี่คือสถานการณ์มาตรฐาน:

if(string.IsNullOrEmpty(Configuration.AppSettings["foobar"]))
   throw new SomeStandardException("Application not configured correctly, bozo.");

ปัญหาคือฉันไม่แน่ใจว่าข้อยกเว้นSomeStandardExceptionใดควรเป็นอย่างยิ่ง

ฉันอ่าน 3.5 Framework และพบผู้สมัครสองคนที่น่าจะเป็น: ConfigurationExceptionและConfigurationErrorsException.

System.Configuration.ConfigurationException

ข้อยกเว้นที่เกิดขึ้นเมื่อเกิดข้อผิดพลาดของระบบคอนฟิกูเรชัน

หมายเหตุ

ConfigurationExceptionยกเว้นจะโยนถ้าความพยายามในการประยุกต์ใช้ในการอ่านหรือเขียนข้อมูลไปยังแฟ้มการกำหนดค่า แต่ไม่ประสบความสำเร็จ สาเหตุที่เป็นไปได้บางประการอาจรวมถึง XML ที่ผิดรูปแบบในไฟล์คอนฟิกูเรชันปัญหาการอนุญาตไฟล์และคุณสมบัติการกำหนดค่าที่มีค่าไม่ถูกต้อง

บันทึก:

ConfigurationExceptionวัตถุจะยังคงเข้ากันได้ย้อนหลัง ConfigurationErrorsException วัตถุแทนที่ระบบการกำหนดค่า

ข้อยกเว้นนี้ฟังดูสมบูรณ์แบบสำหรับสิ่งที่ฉันต้องการ แต่ถูกทำเครื่องหมายว่าล้าสมัยดังนั้น ixnay on atthay

สิ่งนี้ทำให้เรางงอย่างละเอียดConfigurationErrorsException:

System.Configuration.ConfigurationErrorsException

ค่าปัจจุบันไม่ใช่หนึ่งในค่า EnableSessionState

อย่างที่คุณเห็นเอกสารประกอบนั้นไร้ประโยชน์อย่างสิ้นเชิง (เป็นแบบนั้นในความช่วยเหลือทั้งในพื้นที่และออนไลน์) การตรวจสอบในชั้นเรียนแสดงให้เห็นว่าฉันต้องการสิ่งที่ฉันต้องการมากเกินไป

โดยสรุปฉันต้องการข้อยกเว้นมาตรฐานที่ควรทิ้งเมื่อการตั้งค่าการกำหนดค่าแอปพลิเคชันขาดหายไปหรือมีค่าที่ไม่ถูกต้อง คุณคิดว่า Framework มีข้อยกเว้นดังกล่าวสำหรับแอปพลิเคชันที่จะใช้ (เห็นได้ชัดว่าเป็นเช่นนั้น แต่ถูกทำเครื่องหมายว่าล้าสมัยและถูกแทนที่ด้วยขอบเขตที่ใหญ่กว่ามาก )

พวกคุณใช้วิธีแก้ปัญหาอะไรหรือไม่และฉันจะต้องดูดมันขึ้นมาและยกเลิกข้อยกเว้นของตัวเองสำหรับสิ่งนี้หรือไม่?

แก้ไขภาคผนวก

มีบางคนถามว่าฉันสามารถระบุค่าเริ่มต้นได้หรือไม่และดำเนินการต่อ ในบางกรณีใช่และในบางกรณีข้อยกเว้นจะไม่ถูกโยนทิ้ง อย่างไรก็ตามสำหรับการตั้งค่าบางอย่างจะใช้ไม่ได้ ตัวอย่างเช่นชื่อเซิร์ฟเวอร์ฐานข้อมูลและข้อมูลประจำตัวเซิร์ฟเวอร์การพิสูจน์ตัวตนและเส้นทางไปยังแอปพลิเคชันของบุคคลที่สามที่ติดตั้ง

นอกจากนี้ยังเป็นที่น่าสังเกตว่าแอปพลิเคชันที่ฉันใช้งานเป็นหลักคือแอปพลิเคชันคอนโซลที่ทำงานในโหมดแบตช์และฉันต้องการให้มีการยกเว้นที่ถูกจับโดยวิธีการหลักและบันทึกอย่างเหมาะสมหากสิ่งนั้นไม่ได้รับการกำหนดค่าอย่างเหมาะสม (เป็นรหัสเดิมที่ฉันได้รับมาและตอนนี้ถือว่าทุกอย่างเป็นพีช)


1
System.Configuration.ConfigurationErrorsException อัปเดตเอกสารสำหรับแล้ว
slolife

คำตอบ:


36

คุณไม่ได้ จำกัด ข้อยกเว้นของคุณไว้ที่ข้อยกเว้นที่มีอยู่ใน Framework หากคุณตัดสินใจที่จะใช้ข้อยกเว้นที่มีอยู่คุณไม่จำเป็นต้องปฏิบัติตามเอกสารประกอบของจดหมาย เอกสารประกอบจะอธิบายว่ากรอบงานใช้ข้อยกเว้นที่กำหนดอย่างไร แต่ไม่ได้หมายความถึงข้อ จำกัด ใด ๆ เกี่ยวกับวิธีที่คุณเลือกใช้ / ใช้ข้อยกเว้นที่มีอยู่ซ้ำ

เป็นแอปพลิเคชันของคุณตราบเท่าที่คุณจัดทำเอกสารและระบุข้อยกเว้นที่จะเกิดขึ้นในกรณีเฉพาะของค่าการกำหนดค่าที่ขาดหายไปคุณสามารถใช้ข้อยกเว้นที่คุณต้องการได้ หากคุณต้องการระบุค่าที่ขาดหายไปอย่างเฉพาะเจาะจงคุณอาจพิจารณาเขียนข้อยกเว้น ConfigurationSettingMissing ของคุณเอง:

[Serializable]
public class ConfigurationMissingException : ConfigurationErrorsException
{}

แก้ไข: การเขียนข้อยกเว้นของคุณเองในกรณีนี้ถือเป็นประโยชน์เพิ่มเติมในการรับประกันว่าจะไม่มีความสับสนว่าข้อยกเว้นมาจากไหน - กรอบงานหรือแอปพลิเคชันของคุณ เฟรมเวิร์กจะไม่ทิ้งข้อยกเว้นที่กำหนดเองของคุณ

UPDATE: ฉันเห็นด้วยกับความคิดเห็นดังนั้นฉันจึงเปลี่ยนคลาสย่อยเป็น ConfigurationErrorsException จาก Exception ฉันคิดว่าโดยทั่วไปแล้วเป็นความคิดที่ดีที่จะใช้ข้อยกเว้นแบบกำหนดเองของคลาสย่อยจากข้อยกเว้นของ Framework ที่มีอยู่หากเป็นไปได้หลีกเลี่ยงคลาส Exception เว้นแต่คุณจะต้องการข้อยกเว้นเฉพาะแอปพลิเคชัน


17
ฉันไม่เห็นด้วยบ้าง หากคุณจะใช้ข้อยกเว้นที่มีอยู่ควรใช้ให้ถูกต้องตามที่เอกสารระบุว่าใช้แล้วมิฉะนั้นคุณจะสับสนกับผู้ที่มาตามคุณ หากคุณกำลังจะทำอะไรบางอย่างที่แตกต่างออกไปเพียงแค่สร้างข้อยกเว้นของคุณเองเช่นที่คุณพูด
Robert C.Barth

1
ฉันไม่เห็นด้วย. เว้นแต่คุณจะมีสถานการณ์ในการตรวจจับข้อยกเว้นที่กำหนดเองซึ่งไม่น่าเกิดขึ้นในกรณีของข้อผิดพลาดในการกำหนดค่าคุณควรใช้ประเภทที่มีอยู่ซ้ำ (ConfigurationErrorsException) และถ้าคุณสร้าง Type แบบกำหนดเองฉันจะได้มาจาก Type ที่เกี่ยวข้องเช่น ConfigurationErrorsException
โจ

@Robert & Joe- ฉันไม่ได้แนะนำว่าควรใช้ข้อยกเว้น Framework ที่มีอยู่อย่างไม่สอดคล้องกับฟังก์ชันที่ตั้งใจไว้เพียงแค่มีความยืดหยุ่นตราบเท่าที่กรณีเฉพาะ (ค่าที่หายไป) ตรงกับกรณีทั่วไป (ConfigurationErrorsException)
Dave Swersky

1
อาจมีปัญหากับสิ่งนี้หากคุณโยนข้อยกเว้นภายในแอปพลิเคชัน ASP.NET เป็น ConfigurationErrorsException และคลาสที่ได้รับจากแอปนี้จะไม่ติดอยู่ในเมธอด OnError ที่ได้รับการป้องกันหรือเหตุการณ์ Global ASAX Error ดูคำถามที่ฉันโพสต์ไว้ .... stackoverflow.com/questions/25299325/…
มิก

48

โดยส่วนตัวฉันใช้InvalidOperationExceptionเนื่องจากมีปัญหากับสถานะวัตถุไม่ใช่ระบบการกำหนดค่า ท้ายที่สุดคุณไม่ควรอนุญาตให้ตั้งค่าเหล่านี้ด้วยรหัสและไม่กำหนดค่าด้วยหรือไม่? ส่วนสำคัญที่นี่ไม่ใช่ว่าไม่มีบรรทัดใน app.config แต่ไม่มีข้อมูลที่ต้องการ

สำหรับฉัน ConfigurationException (และเป็นการแทนที่ ConfigurationErrorsException - แม้ว่าเอกสาร MSDN ที่ทำให้เข้าใจผิด) เป็นข้อผิดพลาดในการบันทึกการอ่านและอื่น ๆ ของ Configuration


ฉันได้เลือกใช้ InvalidOperationException เนื่องจากจัดการโดยวิธีการ OnError ของเพจ ASP.NET ที่มีการป้องกันในขณะที่ ConfigurationErrorsException และข้อยกเว้นทั้งหมดที่ได้รับจากมันไม่ได้
มิก

2
สิ่งนี้จะทำให้ฉันประหลาดใจจริงๆถ้าฉันได้รับ InvalidOperationException หากฉันกำหนดค่าผิด
keuleJ

18

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

ก่อนที่จะ .NET 2.0 ข้อเสนอแนะคือการใช้System.Configuration.ConfigurationException ConfigurationException ล้าสมัยใน. NET 2.0 ด้วยเหตุผลที่ไม่เคยชัดเจนสำหรับฉันและคำแนะนำเปลี่ยนไปใช้ ConfigurationErrorsException

ฉันใช้วิธีผู้ช่วยในการโยนข้อยกเว้นเพื่อให้ง่ายต่อการเปลี่ยนข้อยกเว้นที่ถูกโยนทิ้งในที่เดียวเมื่อย้ายจาก. NET 1.x เป็น 2.0 หรือถ้า Microsoft ตัดสินใจเปลี่ยนคำแนะนำอีกครั้ง:

if(string.IsNullOrEmpty(Configuration.AppSettings("foobar")))
{
   throw CreateMissingSettingException("foobar");
}

...

private static Exception CreateMissingSettingException(string name)
{
    return new ConfigurationErrorsException(
        String.Format
        (
        CultureInfo.CurrentCulture,
        Properties.Resources.MissingConfigSetting,
        name
        )
        );
}

16

เกี่ยวกับอะไรSystem.Configuration.SettingsPropertyNotFoundException?


IMO นี่คือคำตอบที่แท้จริง +1
LC

ไม่จริงเพราะ: ให้ข้อยกเว้นสำหรับวัตถุ SettingsProperty ที่ไม่พบ ซึ่งมาจาก: ใช้ภายในเป็นคลาสที่แสดงข้อมูลเมตาเกี่ยวกับคุณสมบัติคอนฟิกูเรชันแต่ละรายการ ซึ่งไม่เหมือนกับค่าที่ขาดหายไปของการกำหนดค่า
Karol Haliński

7

ConfigurationErrorsExceptionเป็นข้อยกเว้นที่ถูกต้องสำหรับสถานการณ์ที่คุณอธิบาย เอกสาร MSDN เวอร์ชันก่อนหน้าเพื่อConfigurationErrorsExceptionให้เหมาะสมยิ่งขึ้น

http://msdn.microsoft.com/en-us/library/system.configuration.configurationerrorsexception(VS.80).aspx

สรุปและข้อสังเกต MSDN ก่อนหน้านี้คือ:

  • ข้อยกเว้นที่เกิดขึ้นเมื่อเกิดข้อผิดพลาดของระบบคอนฟิกูเรชัน
  • ConfigurationErrorsException ยกเว้นจะโยนเมื่อข้อผิดพลาดใด ๆ เกิดขึ้นในขณะที่ข้อมูลการกำหนดค่าจะถูกอ่านหรือเขียน

7
จากเอกสารประกอบ: "API นี้สนับสนุนโครงสร้างพื้นฐานของผลิตภัณฑ์และไม่ได้ตั้งใจให้ใช้โดยตรงจากโค้ดของคุณเริ่มต้นอินสแตนซ์ใหม่ของคลาส ConfigurationErrorsException"
Oleg Sh

6

คลาส ConfigurationElement (ซึ่งเป็นคลาสพื้นฐานของคลาสที่เกี่ยวข้องกับการกำหนดค่าจำนวนมากเช่น ConfigurationSection) มีเมธอดที่เรียกว่า OnRequiredPropertyNotFound (มีวิธีการช่วยเหลืออื่น ๆ ด้วย) คุณสามารถโทรหาสิ่งเหล่านั้นได้

OnRequiredPropertyNotFound ถูกนำไปใช้เช่นนี้:

protected virtual object OnRequiredPropertyNotFound(string name) {
    throw new ConfigurationErrorsException(SR.GetString("Config_base_required_attribute_missing", new object[] { name }), this.PropertyFileName(name), this.PropertyLineNumber(name)); }

1

ฉันจะดูดมันขึ้นมาแล้วม้วนเอง ... แต่ก่อนที่จะทำเป็นไปได้ไหมที่ระบบจะถือว่าค่าเริ่มต้นสำหรับการตั้งค่าคอนฟิกนี้ โดยทั่วไปฉันจะพยายามทำเช่นนั้นสำหรับทุกการตั้งค่าที่อาจทำให้พลาด bu Ops Management folk ... .. )

โดยทั่วไปข้อยกเว้นที่กำหนดเองไม่ใช่ความพยายามมากนัก ... นี่คือตัวอย่าง ...

[Serializable]
public class MyCustomApplicationException : ApplicationException
{
    #region privates
    #endregion privates

    #region properties
    #endregion properties

    public MyCustomApplicationException (string sMessage,
        Exception innerException)
        : base(sMessage, innerException) { }
    public MyCustomApplicationException (string sMessage)
        : base(sMessage) { }
    public MyCustomApplicationException () { }

    #region Serializeable Code
    public MyCustomApplicationException (
       SerializationInfo info, StreamingContext context)
        : base(info, context) { }
    #endregion Serializeable Code
}

2
MSDN: ... แอปพลิเคชันที่ต้องการสร้างข้อยกเว้นของตัวเอง [... ] ได้มาจากข้อยกเว้นที่กำหนดเองจากคลาส Exception แต่เดิมคิดว่าข้อยกเว้นที่กำหนดเองควรมาจากคลาส ApplicationException อย่างไรก็ตามในทางปฏิบัติไม่พบว่ามีการเพิ่มมูลค่าอย่างมีนัยสำคัญ
Gaspar Nagy

ใช่ฉันคิดว่าเป็นเพราะโปรแกรมเมอร์ MS ที่เข้ารหัสเฟรมเวิร์กได้รับข้อยกเว้น CLR จำนวนมากจาก ApplicationException จึงทำลายความสำคัญของความแตกต่าง .. ฉันยังคงทำเช่นนั้นเพราะฉันไม่เห็นอันตรายใด ๆ เลย ...
Charles Bretana

1

วิธีทางเลือกที่คุณสามารถใช้สำหรับการ config AppSettingsไฟล์ของคุณจะใช้ส่วนกำหนดค่าที่กำหนดเองเมื่อเทียบกับ ด้วยวิธีนี้คุณสามารถระบุว่าคุณสมบัติIsRequiredและระบบคอนฟิกูเรชันจะจัดการการตรวจสอบนี้ให้คุณ หากคุณสมบัติหายไปConfigurationErrorsExceptionฉันคิดว่ามันสนับสนุนคำตอบที่คุณควรใช้ข้อยกเว้นนั้นในกรณีของคุณ


0

กฎทั่วไปของฉันคือ:

  1. หากกรณีของการกำหนดค่าที่ขาดหายไปไม่ใช่เรื่องธรรมดาและฉันเชื่อว่าฉันไม่ต้องการจัดการกรณีนี้แตกต่างจากข้อยกเว้นอื่น ๆ ฉันเพียงแค่ใช้คลาส "ข้อยกเว้น" พื้นฐานพร้อมข้อความที่เหมาะสม:

    โยนข้อยกเว้นใหม่ ("ข้อความของฉันที่นี่")

  2. หากฉันต้องการหรือคิดว่ามีความเป็นไปได้สูงที่ฉันจะต้องการจัดการกรณีนี้ในลักษณะที่แตกต่างจากข้อยกเว้นอื่น ๆ ส่วนใหญ่ฉันจะม้วนประเภทของตัวเองตามที่มีคนแนะนำไว้แล้วที่นี่


0

ฉันมักจะไม่เห็นด้วยกับคำถามของคุณ:

โดยสรุปฉันต้องการข้อยกเว้นมาตรฐานที่ควรทิ้งเมื่อการตั้งค่าการกำหนดค่าแอปพลิเคชันขาดหายไปหรือมีค่าที่ไม่ถูกต้อง คุณคิดว่า Framework มีข้อยกเว้นดังกล่าวสำหรับแอปพลิเคชันที่จะใช้ (เห็นได้ชัดว่าเป็นเช่นนั้น แต่ถูกทำเครื่องหมายว่าล้าสมัยและถูกแทนที่ด้วยขอบเขตที่ใหญ่กว่ามาก)

ตามเอกสาร MSDN เรื่อง System.Exception ( Exception Classจริงๆแล้วคุณไม่ควรทิ้งข้อยกเว้นสำหรับข้อผิดพลาดในการป้อนข้อมูลของผู้ใช้ด้วยเหตุผลด้านประสิทธิภาพ (ซึ่งผู้อื่นชี้ให้เห็นใน Stack Overflow และที่อื่น ๆ ) สิ่งนี้ดูเหมือนจะสมเหตุสมผล ดี - เหตุใดฟังก์ชันของคุณจึงไม่สามารถส่งคืนเท็จได้หากป้อนข้อมูลของผู้ใช้ไม่ถูกต้องจากนั้นให้แอปพลิเคชันออกอย่างสง่างามดูเหมือนว่าจะเป็นปัญหาในการออกแบบมากกว่าแล้วจึงเป็นปัญหาเกี่ยวกับข้อยกเว้นที่จะโยน

ตามที่คนอื่น ๆ ได้ชี้ให้เห็นหากคุณต้องทิ้งข้อยกเว้นไม่ว่าจะด้วยเหตุผลใดก็ตาม - ไม่มีเหตุผลใดที่คุณไม่สามารถกำหนดประเภท Exception ของคุณได้โดยการสืบทอดจาก System.Exception


2
เหตุใดประสิทธิภาพจึงมีความสำคัญในสถานการณ์เฉพาะนี้ IUC จากนั้นข้อยกเว้นจะถูกโยนเพียงครั้งเดียวและกระบวนการจะหยุดลงในภายหลังอยู่ดี (แน่นอนว่าหลังจากแสดงป๊อปอัปที่ดีให้กับผู้ใช้) (ยังมีต่อ ... )

2
การส่งคืนรหัสข้อผิดพลาดแทนที่จะโยนข้อยกเว้นอาจเป็นเรื่องที่เจ็บปวดเพราะจากนั้นคุณจะต้องเผยแพร่ข้อมูลข้อผิดพลาดในกลุ่มการโทรด้วยตัวคุณเอง คุณควรใช้ข้อยกเว้นสำหรับข้อผิดพลาดที่เกิดขึ้นได้ยากซึ่งอาจแพร่กระจายในหลาย ๆ เฟรมสแต็ก ทั้งสองใช้ที่นี่

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

2
ในแอปพลิเคชันเฉพาะนี้เกือบทั้งหมดขับเคลื่อนโดยการตั้งค่าในไฟล์กำหนดค่า หากไม่มีการตั้งค่า (ที่เข้ารหัส) แอปพลิเคชันจะดำเนินการต่อไม่ได้และต้องยุติ จำเป็นต้องมีข้อยกเว้น
Mike Hofer

1
สิ่งนี้สามารถเข้าสู่ความหมายได้อย่างแน่นอนและโครงสร้างของโค้ดของคุณจะกำหนดการนำไปใช้งานที่ดีที่สุดสำหรับสถานการณ์ของคุณอย่างชัดเจน ถึงกระนั้นหากคุณมีอิสระในการออกแบบฉันจะยังคงไปกับวัตถุเพื่อบันทึกข้อผิดพลาดและทางออกที่สง่างามเหนือข้อยกเว้นประสิทธิภาพเป็นปัญหาหรือไม่
Matt Jordan

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