ไวยากรณ์ที่ราบรื่นและน่าดึงดูดที่สุดที่คุณพบในการยืนยันความถูกต้องของพารามิเตอร์ใน c# คืออะไร

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

ขั้นแรก โค้ดที่ไม่มีตัวช่วย:

public void SomeMethod(string firstName, string lastName, int age)
{
     if(firstName == null)
     {
          throw new WhateverException("The value for firstName cannot be null.");
     }

     if(lastName == null)
     {
          throw new WhateverException("The value for lastName cannot be null.");
     }

     // Same kind of code for age, making sure it is a reasonable range (< 150, for example).
     // You get the idea
}

}

ตอนนี้ รหัสพยายามช่วยเหลืออย่างสมเหตุสมผล:

public void SomeMethod(string firstName, string lastName, int age)
{
      Helper.Validate( x=> x !=null, "firstName", firstName);
      Helper.Validate( x=> x!= null, "lastName", lastName);
}

คำถามหลักคือ: สังเกตว่าโค้ดต้องส่งค่าของพารามิเตอร์ และ ชื่อของพารามิเตอร์ ("firstName" และ อย่างไร ชื่อจริง). ทั้งนี้เพื่อให้ข้อความแสดงข้อผิดพลาดสามารถแจ้งว่า "บลา บลา บลา ค่าสำหรับพารามิเตอร์ ชื่อแรก" คุณพบวิธีที่จะแก้ไขปัญหานี้โดยใช้การไตร่ตรองหรือสิ่งอื่นใดหรือไม่? หรือมีวิธีทำให้เจ็บน้อยลง?

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

แก้ไข: ฉันได้อ่านผู้คนที่พูดถึงการใช้คุณสมบัติพารามิเตอร์ แต่ไม่เคยพบวิธีแก้ไขการทำซ้ำเลย มีใครโชคดีกับสิ่งนั้นบ้างไหม?

ขอบคุณ!


person Charlie Flowers    schedule 21.03.2009    source แหล่งที่มา
comment
ไม่แนะนำให้ใช้คลาส ApplicationException   -  person mmx    schedule 21.03.2009
comment
โอเค ฉันเปลี่ยนเป็นข้อยกเว้นแล้วเพื่อหลีกเลี่ยงสิ่งรบกวนสมาธิ นอกจากนี้ หากคำแนะนำนั้นอิงจากความคิดเห็นของผู้เขียนหนังสือ Framework Guidelines ฉันก็ไม่ค่อยมั่นใจนัก (แม้ว่าคนเหล่านั้นจะเขียนสิ่งดีๆ ไว้บ้างก็ตาม) แต่นั่นคือการสนทนาสำหรับวันอื่น   -  person Charlie Flowers    schedule 21.03.2009
comment
เฮงก์: ผิด. ใดๆ ไม่แนะนำให้ใช้ ApplicationException ดูส่วนหมายเหตุที่นี่ โดยเฉพาะย่อหน้าที่สอง: msdn.microsoft.com /en-us/library/   -  person Ryan Lundy    schedule 14.12.2009
comment
@Kyralessa หากนั่นเป็นการอ้างอิงเพียงอย่างเดียวสำหรับสิ่งนี้ นั่นเป็นข้อโต้แย้งที่ค่อนข้างไม่จำเป็น ไม่มีเหตุผลสำคัญ 1 ประการว่าทำไมคุณไม่ควรใช้ข้อยกเว้นของแอปพลิเคชันในส่วนหมายเหตุนั้น มันยังบอกโดยตรงด้วยว่าเดิมทีคิดว่าข้อยกเว้นแบบกำหนดเองควรได้มาจากคลาส ApplicationException อย่างไรก็ตามในทางปฏิบัติไม่พบว่าจะเพิ่มมูลค่าอย่างมีนัยสำคัญ โดยพื้นฐานแล้ว MS ยอมรับว่าไม่จำเป็นต้องใช้คลาส ApplicationException ไม่ใช่ว่าใช้งานไม่ดี   -  person Chris Marisic    schedule 16.03.2011


คำตอบ (14)


สิ่งนี้อาจเป็นประโยชน์บ้าง:

ออกแบบโดยสัญญา/C# 4.0/หลีกเลี่ยง ArgumentNullException

person core    schedule 21.03.2009
comment
ขอบคุณ! สิ่งนี้นำไปสู่ ​​2 แนวทางที่ทำให้ฉันทึ่ง! และฉันเห็นว่าใช้ทั้งสองอย่าง - person Charlie Flowers; 22.03.2009
comment
การใช้การตรวจสอบความถูกต้องอย่างคล่องแคล่วนั้นค่อนข้างราบรื่นฮะ - person core; 22.03.2009
comment
ใช่มันเนียนมาก ฉันไม่รู้ว่าคุณสามารถเรียกใช้เมธอดส่วนขยายบนตัวแปรที่เป็นโมฆะได้ ฉันไม่รู้ว่า Anders ตั้งใจให้มันเกิดขึ้นหรือว่ามันเป็นผลข้างเคียง ไม่ว่าจะด้วยวิธีใดก็มีประโยชน์มาก - person Charlie Flowers; 22.03.2009
comment
ชาร์ลี ใช่ ฉันเอาแต่คิดว่า โอเค ตอนนี้มันไม่ถูกต้องแล้ว แล้ว NullReferenceException ล่ะ? จนกระทั่งผมเลื่อนลงไปดูวิธีการขยาย ข้อตกลงที่ยอดเยี่ยม - person core; 23.03.2009
comment
คำตอบนี้สอนฉันมากที่สุด ต้องให้เครดิตเมื่อเครดิตถึงกำหนด ขอขอบคุณทุกคนสำหรับการตอบรับที่ดีเยี่ยม! - person Charlie Flowers; 24.03.2009

คุณควรตรวจสอบ สัญญารหัส; พวกเขาทำสิ่งที่คุณถามค่อนข้างทุกประการ ตัวอย่าง:

[Pure]
public static double GetDistance(Point p1, Point p2)
{
    CodeContract.RequiresAlways(p1 != null);
    CodeContract.RequiresAlways(p2 != null); 
    // ...
}
person John Feminella    schedule 21.03.2009
comment
เฮ้ เยี่ยมเลย ... โดยเฉพาะอย่างยิ่งมันจะถูกสร้างเป็นภาษาใน c# 4.0 แต่ถึงกระนั้น ... ในระหว่างนี้เราจะทำอะไรได้บ้าง? - person Charlie Flowers; 21.03.2009
comment
พวกมันจะถูกอบใน .NET 4 แต่ตอนนี้คุณยังสามารถใช้งานได้ พวกเขาไม่ได้ขึ้นอยู่กับสิ่งใดที่เฉพาะเจาะจงกับ .NET 4 ดังนั้นคุณจึงสามารถย้อนกลับไปเป็น 2.0 ได้หากต้องการ โครงการอยู่ที่นี่: research.microsoft.com/en-us/projects/contracts< /ก> - person John Feminella; 21.03.2009
comment
คุณสามารถทำงานในชั้นเรียนของคุณเองซึ่งมีหน้าตาแบบนั้นได้ แต่มีข้อยกเว้นสำหรับไลบรารี ค่อนข้างง่ายที่จะเขียนขึ้นมา - person user7116; 22.03.2009
comment
แต่คุณเคยลองใช้ Code Contract กับ Project ที่ใหญ่กว่าบ้างไหม? ขออภัย ใช้งานไม่ได้ เวลาในการคอมไพล์เพิ่มขึ้นมากเกินไป - person Mic; 10.08.2012

ว้าว ฉันพบสิ่งที่น่าสนใจจริงๆ ที่นี่ Chris ด้านบนให้ลิงก์ไปยังคำถาม Stack Overflow อื่น หนึ่งในคำตอบนั้นชี้ไปที่โพสต์บล็อกซึ่งอธิบายวิธีรับโค้ดดังนี้:

public static void Copy<T>(T[] dst, long dstOffset, T[] src, long srcOffset, long length)
{
    Validate.Begin()
            .IsNotNull(dst, “dst”)
            .IsNotNull(src, “src”)
            .Check()
            .IsPositive(length)
            .IsIndexInRange(dst, dstOffset, “dstOffset”)
            .IsIndexInRange(dst, dstOffset + length, “dstOffset + length”)
            .IsIndexInRange(src, srcOffset, “srcOffset”)
            .IsIndexInRange(src, srcOffset + length, “srcOffset + length”)
            .Check();

    for (int di = dstOffset; di < dstOffset + length; ++di)
        dst[di] = src[di - dstOffset + srcOffset];
}

ฉันยังไม่มั่นใจว่านี่เป็นคำตอบที่ดีที่สุด แต่ก็น่าสนใจอย่างแน่นอน นี่คือโพสต์ในบล็อก , จากริค บรูว์สเตอร์.

person Charlie Flowers    schedule 22.03.2009

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

นี่คือวิธีแก้ปัญหาของฉัน

สรุปโดยย่อ - รับโค้ดเล็กน้อยนี้:

int x = 3;
string t = "hi";
Assert(() => 5*x + (2 / t.Length) < 99);

ฟังก์ชัน Assert ของฉันสามารถพิมพ์ข้อมูลสรุปของสิ่งที่ส่งผ่านไปได้ดังต่อไปนี้:

(((5 * x) + (2 / t.Length)) < 99) == True where
{
  ((5 * x) + (2 / t.Length)) == 16 where
  {
    (5 * x) == 15 where
    {
      x == 3
    }
    (2 / t.Length) == 1 where
    {
      t.Length == 2 where
      {
        t == "hi"
      }
    }
  }
}

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

person Daniel Earwicker    schedule 21.03.2009
comment
ว้าว มันเยี่ยมมาก ฉันไม่รู้ว่าทำไมฉันไม่คิดอย่างนั้น (ความคิดดีๆ มักจะกระตุ้นความรู้สึกนั้น) ฉันกำลังเขียนแอปคำนวณซึ่งอาจมีประโยชน์มากในแง่ของการอธิบายคำตอบที่ได้รับ - person Charlie Flowers; 21.03.2009
comment
การรวมกันของแผนผังการสะท้อนและการแสดงออกทำให้เกิดสิ่งต่างๆ มากมายที่ทำให้คุณประหลาดใจ โดยเฉพาะอย่างยิ่ง ถ้า (เช่นฉัน) คุณมาจากพื้นหลัง C/C++ ที่ไม่มีรันไทม์อยู่ เราต้องคิดค้นสิ่งที่ Lispers ทำมาครึ่งศตวรรษขึ้นมาใหม่! - person Daniel Earwicker; 21.03.2009
comment
เป็นความคิดที่ดี และยังใช้สำหรับแอป Calc ด้วย! - person flq; 21.03.2009

เอาล่ะ ทุกคน ฉันอีกแล้ว และฉันพบสิ่งอื่นที่น่าอัศจรรย์และน่ายินดี เป็นอีกหนึ่งบล็อกโพสต์ที่อ้างอิงมาจากคำถาม SO อื่น ๆ ที่ Chris กล่าวถึงข้างต้น

วิธีการของผู้ชายคนนี้ให้คุณเขียนสิ่งนี้:

public class WebServer
    {
        public void BootstrapServer( int port, string rootDirectory, string serverName )
        {
            Guard.IsNotNull( () => rootDirectory );
            Guard.IsNotNull( () => serverName );

            // Bootstrap the server
        }
    }

โปรดทราบว่าไม่มีสตริงที่มี "rootDirectory" และไม่มีสตริงที่มี "serverName"!! แต่ข้อความแสดงข้อผิดพลาดของเขาสามารถพูดบางอย่างเช่น "พารามิเตอร์ rootDirectory ต้องไม่เป็นค่าว่าง"

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

และการนำไปปฏิบัตินั้นค่อนข้างง่ายดังนี้:

public static class Guard
    {
        public static void IsNotNull<T>(Expression<Func<T>> expr)
        {
            // expression value != default of T
            if (!expr.Compile()().Equals(default(T)))
                return;

            var param = (MemberExpression) expr.Body;
            throw new ArgumentNullException(param.Member.Name);
        }
    }

โปรดทราบว่าวิธีนี้ใช้ "การสะท้อนแบบคงที่" ดังนั้นในการวนซ้ำที่แน่นหนาหรือบางอย่าง คุณอาจต้องการใช้แนวทางของ Rick Brewster ข้างต้น

ทันทีที่ฉันโพสต์สิ่งนี้ ฉันจะโหวตให้คริสและการตอบคำถาม SO อีกข้อหนึ่ง นี่คือสิ่งดีๆ!!!

person Charlie Flowers    schedule 22.03.2009
comment
สวัสดี ฉันสังเกตเห็นสิ่งนี้ช้าไปหน่อย แต่ฉันคิดว่ามันขาดพลังทั่วไปของการแสดงออกไปสักหน่อย ดูคำตอบของฉันอีกครั้ง - คุณไม่จำเป็นต้องเขียนฟังก์ชันแยกต่างหากสำหรับการยืนยันแต่ละประเภทที่คุณอาจต้องการ เพียงเขียนนิพจน์ในรูปแบบ C# ปกติ: X.Assert(() => serverName != null); ไม่มีเหตุผลที่ดีที่จะสะสมชุดของวิธีการพิเศษ (IsNull, IsNotNull, AreEqual ฯลฯ) หนึ่งชุดสำหรับการยืนยันแต่ละประเภท เนื่องจากเราสามารถรับคำอธิบายที่สมบูรณ์ของนิพจน์ใดๆ และทั้งหมดได้ ค่าต่างๆ ในนั้น ไม่ว่านิพจน์จะเป็นเช่นไรก็ตาม - person Daniel Earwicker; 06.08.2009
comment
เอียร์วิคเกอร์ นั่นเป็นข้อสังเกตที่น่าสนใจ ฉันชอบมัน แม้ว่ามันจะไม่ใช่สแลมดังค์และอาจมีบางกรณีที่ฉันใช้แนวทางหลายวิธี (IsNull, IsNotNull ฯลฯ) หรืออย่างน้อยฉันก็จะถกเถียงกับตัวเองเกี่ยวกับเรื่องนี้ ข้อความแสดงข้อผิดพลาดอาจสวยกว่าที่บอกว่า FirstName ไม่สามารถเป็นโมฆะได้มากกว่า The assertion (FirstName != null) failed นอกจากนี้ถ้าคุณมีร้อยแห่งที่คุณยืนยัน (บางอย่าง != null) นั่นก็ให้ความรู้สึกเหมือนการทำโค้ดซ้ำ ฉันไม่แน่ใจว่าเป็นการทำซ้ำที่เป็นอันตรายหรือไม่ ก็คงแล้วแต่. แต่การสังเกตที่ยอดเยี่ยมขอบคุณ - person Charlie Flowers; 17.08.2009

การใช้ห้องสมุดของฉัน The Helper Trinity:

public void SomeMethod(string firstName, string lastName, int age)
{
    firstName.AssertNotNull("firstName");
    lastName.AssertNotNull("lastName");

    ...
}

นอกจากนี้ยังสนับสนุนการยืนยันว่าพารามิเตอร์การแจงนับถูกต้อง คอลเลกชันและเนื้อหาไม่ใช่ null พารามิเตอร์สตริงไม่ว่างเปล่า ฯลฯ ดูเอกสารประกอบผู้ใช้ที่นี่ สำหรับตัวอย่างโดยละเอียด .

person Kent Boogaart    schedule 21.03.2009
comment
+1. ฉันชอบใช้วิธีการขยายเพื่อลดจำนวนคำ ฉันจะเรียกเมธอด MustNotBeNull หรืออะไรสักอย่างแทน แต่นั่นเป็นเพียงความชอบส่วนตัว - person Orion Edwards; 22.03.2009
comment
จะเกิดอะไรขึ้นในโค้ดนั้นถ้า firstName เป็นโมฆะ? NullRef จะไม่ตามมาใช่ไหม ไม่เคยพยายามดูว่า Extension Methods ยังสามารถแนบกับตัวชี้ว่างได้หรือไม่ - person Jarrod Dixon♦; 22.03.2009
comment
@Jarrod วิธีการขยายเป็นแบบคงที่ ดังนั้นในวิธีการขยายคุณสามารถทดสอบได้ว่าเป้าหมาย 'this' เป็นโมฆะหรือไม่ - person ProfK; 22.03.2009
comment
@ProfK - เจ๋งมาก! +1 สำหรับคำตอบนี้เช่นกัน - person Jarrod Dixon♦; 23.03.2009
comment
ฉันไม่รู้ด้วยซ้ำว่าคุณสามารถเรียกวิธีการขยายเป็นโมฆะได้จนกว่าฉันจะเริ่มเห็นคำตอบบางส่วนที่นี่ นี่เป็นเรื่องที่ยอดเยี่ยมเพราะมันเปิดหลายสิ่งหลายอย่างซึ่งส่งผลให้มีไวยากรณ์ที่คล่องแคล่วมากขึ้น - person Charlie Flowers; 23.03.2009

นี่คือคำตอบของฉันสำหรับปัญหา ฉันเรียกมันว่า "Guard Claws" มันใช้ตัวแยกวิเคราะห์ IL จาก Lokad Shared Libs แต่มีแนวทางที่ตรงไปตรงมามากกว่าในการระบุส่วนคำสั่งการป้องกันจริง:

string test = null;
Claws.NotNull(() => test);

คุณสามารถดูตัวอย่างการใช้งานเพิ่มเติมได้ในspecs .

เนื่องจากมันใช้แลมบ์ดาจริงเป็นอินพุตและใช้ IL Parser เพื่อสร้างข้อยกเว้นในกรณีของการละเมิดเท่านั้น จึงควรทำงานได้ดีกว่าบน "เส้นทางที่มีความสุข" มากกว่าการออกแบบที่ใช้ Expression ที่อื่นในคำตอบเหล่านี้

ลิงก์ใช้งานไม่ได้ นี่คือ URL: http://github.com/littlebits/guard_claws/

person brendanjerwin    schedule 05.07.2009
comment
เย็น. มีแผนจะใช้ params args เพื่อตรวจสอบตัวแปรหลายตัวหรือไม่ - person Charlie Flowers; 07.07.2009

ไลบรารีที่ใช้ร่วมกันของ Lokad ยังมีการดำเนินการตามการแยกวิเคราะห์ IL ซึ่งหลีกเลี่ยงการทำซ้ำชื่อพารามิเตอร์ในสตริง

ตัวอย่างเช่น:

Enforce.Arguments(() => controller, () => viewManager,() => workspace);

จะส่งข้อยกเว้นด้วยชื่อพารามิเตอร์ที่เหมาะสมหากอาร์กิวเมนต์ใด ๆ ที่ระบุไว้เป็นโมฆะ นอกจากนี้ยังมีการใช้กฎตามนโยบายที่ประณีตจริงๆ

e.g.

Enforce.Argument(() => username,    StringIs.Limited(3, 64), StringIs.ValidEmail);
person Nick Cox    schedule 18.06.2009

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

Helper.Validate( firstName != null || !string.IsNullOrEmpty(directoryID),
                 "The value for firstName cannot be null if a directory ID is not supplied." );
person tvanfosson    schedule 21.03.2009

ไม่รู้ว่าเทคนิคนี้ถ่ายโอนจาก C/C++ ไปเป็น C# หรือไม่ แต่ฉันได้ทำสิ่งนี้ด้วยมาโคร:


    #define CHECK_NULL(x)  { (x) != NULL || \
           fprintf(stderr, "The value of %s in %s, line %d is null.\n", \
           #x, __FILENAME__, __LINE__); }
 
person Adam Liss    schedule 21.03.2009
comment
นั่นคือสิ่งที่ฉันหวังไว้อย่างแน่นอน แต่อย่าคิดว่ามันสามารถทำได้โดยตรงใน c# - person Charlie Flowers; 21.03.2009
comment
C# ไม่รองรับเทคนิคตัวประมวลผลล่วงหน้าที่คุณพบในคอมไพเลอร์ C++ - person Brian Rasmussen; 21.03.2009

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

ในบรรดาเหล่านั้น .. System.ArgumentException, System.ArgumentNullException...

person markt    schedule 21.03.2009
comment
ตกลง แต่ได้โปรด ... อย่ามุ่งเน้นไปที่ประเภทข้อยกเว้น นั่นเป็นส่วนเสริมของประเด็นหลักที่นี่ ดังนั้นฉันจึงพิมพ์สิ่งแรกที่ผุดขึ้นมาในหัว - person Charlie Flowers; 21.03.2009
comment
ก็ได้.. แต่ฉันเชื่อว่าเมื่อใดก็ตามที่คุณโยนข้อยกเว้น การโยนประเภทข้อยกเว้นที่มีประโยชน์ถือเป็นสิ่งสำคัญอย่างยิ่ง - person markt; 21.03.2009

Postsharp หรือ AOP เฟรมเวิร์ก.

person Kris Erickson    schedule 21.03.2009

ไม่สามารถใช้ได้กับทุกที่ แต่อาจช่วยได้ในหลายกรณี:

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

ผลลัพธ์ที่ได้จะเป็นดังนี้:

public void SomeMethod(Person person)
{
    person.CheckInvariants();
    // code here ...
}

การโทรจะเป็นดังนี้ (ถ้าคุณใช้ .NET 3.5):

SomeMethod(new Person { FirstName = "Joe", LastName = "White", Age = 12 });

ภายใต้สมมติฐานว่าชั้นเรียนจะเป็นดังนี้:

public class Person
{
    public string FirstName { get; set; }
    public string LastName { get; set; }
    public int Age { get; set; }

    public void CheckInvariants()
    {
        assertNotNull(FirstName, "first name");
        assertNotNull(LastName, "last name");
    }

    // here are your checks ...
    private void assertNotNull(string input, string hint)
    {
        if (input == null)
        {
            string message = string.Format("The given {0} is null.", hint);
            throw new ApplicationException(message);
        }
    }

แทนที่จะใช้น้ำตาลวากยสัมพันธ์ของ .NET 3.5 คุณยังสามารถใช้อาร์กิวเมนต์ตัวสร้างเพื่อสร้างวัตถุบุคคลได้

person Theo Lenndorff    schedule 22.03.2009

ในทางตรงกันข้าม สิ่งนี้ โพสต์โดย Miško Hevery บน บล็อกการทดสอบของ Google แย้งว่าการตรวจสอบพารามิเตอร์ประเภทนี้อาจไม่ใช่สิ่งที่ดีเสมอไป ผลการถกเถียงในความคิดเห็นยังทำให้เกิดประเด็นที่น่าสนใจอีกด้วย

person Henrik Gustafsson    schedule 22.03.2009
comment
มีความจริงในมุมมองนี้ ฉันไม่จำเป็นต้องพูดถึงการบังคับใช้สัญญาตามหลักศาสนา (ฉันคิดว่านั่นเป็นสิ่งที่ดีในบางกรณีแต่ไม่ใช่ทั้งหมด) แต่ถึงกระนั้น วิธีการบางอย่างจำเป็นต้องทำการตรวจสอบ และบ่อยครั้งที่คุณต้องการความช่วยเหลือในกรณีเหล่านั้น - person Charlie Flowers; 23.03.2009
comment
แน่นอนว่าการตรวจสอบประเภทนี้มีประโยชน์ในหลาย ๆ สถานการณ์ ฉันแค่ต้องการความคิดเห็นที่ตรงกันข้ามสำหรับคนรุ่นต่อ ๆ ไป :) - person Henrik Gustafsson; 23.03.2009