คุณสมบัติที่มีประโยชน์ที่สุด [ปิด]


784

ฉันรู้ว่าคุณลักษณะมีประโยชน์มาก มีบางอย่างที่กำหนดไว้ล่วงหน้าเช่น[Browsable(false)]ที่ช่วยให้คุณสามารถซ่อนคุณสมบัติในแท็บคุณสมบัติ นี่เป็นคำถามที่ดีที่อธิบายคุณลักษณะ: อะไรคือคุณสมบัติใน. NET

อะไรคือคุณสมบัติที่กำหนดไว้ล่วงหน้า (และ namespace) ที่คุณใช้จริงในโครงการของคุณ?


27
คำถามอะไร หน้าทั้งหมดเต็มไปด้วยคำตอบที่สวยงามพร้อมคำอธิบายที่ยอดเยี่ยม ขณะที่ฉันอ่านสิ่งนี้ฉันได้รับประสบการณ์เช่นการสัมภาษณ์ผู้เชี่ยวชาญหลายคนเกี่ยวกับมุมมองของพวกเขา +100 สำหรับคำถาม
Muthu Ganapathy Nathan

ฉันเห็นด้วยคำถามเช่นนี้เป็นคำถามที่มีค่าที่สุด - ทำให้มีประโยชน์น้อยลง
David Thielen

คำตอบ:


669

[DebuggerDisplay]สามารถเป็นประโยชน์อย่างยิ่งในการดูเอาต์พุตแบบกำหนดเองของประเภทเมื่อคุณเลื่อนเมาส์ไปที่อินสแตนซ์ของ Type ในระหว่างการดีบัก ตัวอย่าง:

[DebuggerDisplay("FirstName={FirstName}, LastName={LastName}")]
class Customer
{
    public string FirstName;
    public string LastName;
}

นี่คือลักษณะที่ควรมีในตัวแก้ไขข้อบกพร่อง:

ข้อความแสดงแทน

นอกจากนี้ยังเป็นสิ่งที่ควรค่าแก่การกล่าวถึงว่า[WebMethod]คุณลักษณะพร้อมCacheDurationชุดคุณสมบัติสามารถหลีกเลี่ยงการใช้วิธีการบริการเว็บโดยไม่จำเป็น


62
ว้าวดีจริงๆที่รู้ ฉันมักจะทำสิ่งเดียวกันโดยการเอาชนะ ToString แต่มันดีกว่า
ไบรอัน

17
ระวังด้วยสิ่งนี้มันกัดก้อนใหญ่ออกจาก CPU ของคุณกว่า ToString
Nikola Radosavljević

1
คุณยังสามารถใช้สิ่งนี้เพื่อแสดงผลลัพธ์ของวิธีการต่างๆ สิ่งนี้สามารถสร้างประสบการณ์การดีบักที่ค่อนข้างสับสนหากวิธีการ (หรือคุณสมบัติรับ) มีผลข้างเคียง
Øyvind Skaar

4
@ NikolaRadosavljevićจะใช้พลังงาน CPU ในระหว่างการดีบักเท่านั้น
Nickolay Kondratyev

2
@Nickolay Kondratyev: ฉันไม่ทราบรายละเอียดทั้งหมด แต่คุณสามารถดูแนวทางปฏิบัติที่ดีที่สุดสำหรับบริการบนเว็บซึ่งจะนำคุณไปสู่ข้อสรุปบางประการ: blogs.msdn.com/b/jaredpar/archive/2011/03/ 18 / …
Nikola Radosavljević

273

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

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

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


50
คุณสามารถส่ง "true" เป็นพารามิเตอร์อย่างใดอย่างหนึ่งไปยัง System.Obsolete ซึ่งทำให้คำเตือนกลายเป็นข้อผิดพลาดดังนั้นการทำลายการสร้าง เห็นได้ชัดว่าควรทำเมื่อคุณล้างคำเตือนทั้งหมดแล้ว :)
Adrian Clark

14
เมื่อคุณล้างคำเตือนทั้งหมดแล้วจะเป็นการดีกว่าหรือที่จะลบวิธีนี้
Pedro

10
@Pedro: บางครั้งคุณไม่สามารถย้อนกลับด้วยเหตุผลด้านความเข้ากันได้ หากเป็นส่วนตัวและไม่ได้ใช้ให้ลบออก
Fantius

3
@plinth การโยนข้อยกเว้นจะเป็นความคิดที่ไม่ดีด้วยเหตุผลหลายประการ # 1 เหตุผลหลักที่ใช้ Obsolete () คือเพื่อให้คุณสามารถรวบรวมโค้ดที่คอมไพล์ได้ในขณะที่อยู่ในช่วงการเปลี่ยนภาพ หากคุณไม่อนุญาตให้ใครโทรหาวิธีการทำไมไม่ลบเพียงแค่นั้น
Dan Herbert

17
@plinth เป็นการป้องกันไม่ให้โค้ดใหม่ใช้วิธีนี้ รหัสเก่าจะยังคงใช้งานร่วมกันได้ไบนารีหากวิธีการทำเครื่องหมายล้าสมัย แต่จะหยุดทำงานถ้าคุณโยนข้อยกเว้น หากมีใครใช้สะท้อนการรับรอบ "Obsolte ธง" แล้วคุณมีปัญหาแย่ลง ...
แดนเฮอร์เบิร์

204

[Flags]ค่อนข้างมีประโยชน์ น้ำตาลซินแทคติกต้องแน่ใจ แต่ก็ยังค่อนข้างดี

[Flags] 
enum SandwichStuff
{
   Cheese = 1,
   Pickles = 2,
   Chips = 4,
   Ham = 8,
   Eggs = 16,
   PeanutButter = 32,
   Jam = 64
};

public Sandwich MakeSandwich(SandwichStuff stuff)
{
   Console.WriteLine(stuff.ToString());
   // ...
}

// ...

MakeSandwich(SandwichStuff.Cheese 
   | SandwichStuff.Ham 
   | SandwichStuff.PeanutButter);
// produces console output: "Cheese, Ham, PeanutButter"

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


ดังนั้นคุณสมบัติแอ็ตทริบิวต์ Flags จะทำอย่างไร
Andrei Rînea

13
ฉันหวังว่าพวกคุณจะรู้ว่าการตั้งค่าสถานะนั้นทำให้ทุกคนในระบบ มันไม่จำเป็น / ใช้เลยยกเว้น TypeConverter
leppie

3
@leppie: ToString () เช่นกัน แต่ ... ว้าว ด้วยเหตุผลบางอย่างฉันได้รับการคาดหวังพฤติกรรมของการแจกแจงโดยไม่ต้องแอตทริบิวต์ที่จะเป็นเช่นเดียวกับ C ++: หรือค่านิยมผลิตจำนวนเต็ม (ไม่สามารถส่งผ่านตามที่เป็นวิธีการคาดหวัง Enum Param) ฉันเห็นตอนนี้ไม่ใช่กรณี อ่อนแอ ... ตกลง. NET enums ดูด
Shog9

2
[แฟล็ก] ช่วยให้ดีบักเกอร์และฟังก์ชั่น. ToString () รู้ว่าค่าอาจเป็นการรวมกันของการประกาศหลาย ๆ ค่าใน enum ฉันไม่แน่ใจว่ามันอาจทำให้ Intellisense ช่วยให้คุณใช้ Enum ได้อย่างมีประสิทธิภาพเช่นกัน
Kenzi

31
[Flags]จะมีการใช้ที่ใหญ่กว่าการเป็นเพียงน้ำตาลประโยค ในขณะที่ใช้บริการเว็บการทำให้เป็นอนุกรม / การทำให้เป็นอนุกรมจะไม่ทำงานหากมีการส่งค่าเช่นSandwichStuff.Cheese | SandwichStuff.Ham | SandwichStuff.Jamนี้ โดยไม่ต้อง[Flags]แอตทริบิวต์ deserializer จะไม่ทราบว่าค่าที่จะเป็นการรวมกันของธง เรียนรู้วิธีนี้ยากหลังจากใช้เวลาประมาณสองวันในการคิดว่าทำไม WCF ของฉันไม่ทำงาน
Anchit

177

ผมชอบ[DebuggerStepThrough]จาก System.Diagnostics

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


5
หลายครั้งที่ฉันต้องการให้ฉันรู้เกี่ยวกับคุณสมบัตินี้
wusher

1
น่าเสียดายที่มันถูกทำลายด้วยการปิด - ดูgregbeech.com/blogs/tech/archive/2008/10/17/…สำหรับข้อมูลเพิ่มเติม
Greg Beech

3
นอกจากนี้ยังมีประโยชน์สำหรับรหัส WM_PAINT ใด ๆ ที่คุณรู้ว่าผลงาน :)
Pondidum

@GregBeech URL นั้นส่งคืนข้อผิดพลาด. NET Classy! :)
smdrager

@smdrager - ต้องเป็นปัญหาชั่วคราวดูเหมือนจะทำงานให้ฉันวันนี้
เกร็ก Beech

135

สำหรับสิ่งที่คุ้มค่าต่อไปนี้เป็นรายการของแอตทริบิวต์ .NET ทั้งหมด มีหลายร้อย

ฉันไม่รู้เกี่ยวกับคนอื่น แต่ฉันมี RTFM อย่างจริงจังที่ต้องทำ!


33
รายการที่โพสต์มีไว้สำหรับ. net 1.1 นี่คือรายการสำหรับ 3.5 msdn.microsoft.com/en-us/library/system.attribute.aspx (คุณต้องเลื่อนลงมาเล็กน้อย)
kay.one

2
อัปเดตลิงก์ในคำถาม ตอนนี้เป็นรายการเต็มรูปแบบสำหรับ 3.5
R. Martinho Fernandes

8
ที่จริงแล้วลิงค์ไปยังล่าสุดไม่ใช่ 3.5 โดยเฉพาะ
Brian Ortiz

1
ตอนนี้ถ้าเพียงรายการไม่ได้เป็นเพียงรายการลิงก์ แต่ชื่อและคำอธิบาย โอ้ดี @BrianOrtiz ถูกต้อง รายการนี้เป็นเวอร์ชัน 4.5
ส่องสว่าง

คุณเพียงแค่เปลี่ยนเฟรมเวิร์กที่คุณกำหนดเป้าหมายไว้ที่ด้านบนซึ่งมันระบุว่า "เวอร์ชันอื่น"
Novaterata

129

คะแนนของฉันจะเป็น Conditional

[Conditional("DEBUG")]
public void DebugOnlyFunction()
{
    // your code here
}

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


5
ไม่เหมือนกับการทำ #if DEBUG ไหม
Neil N

10
#if DEBUG หมายความว่าผู้โทรต้องไม่เรียกมันในขณะที่ Conditioinal ออกจากการโทร แต่ทำให้เป็น NOP ที่ถูกกำจัดที่ JIT
Rangoric

23
นอกจากนี้คุณมักจะใช้ #if DEBUG รอบโทรและ [เงื่อนไข] รอบวิธี ดังนั้นหากคุณเรียกใช้วิธีการดีบั๊ก 100 ครั้งการปิดเครื่องจะเป็นเรื่องของการเปลี่ยนรหัสเดียวไม่ใช่ 100
Steve Cooper

13
ความคิดเห็นของ Rangoric ผิดอย่างละเอียด (อย่างน้อยสำหรับ C #): วิธีการดังกล่าวไม่รวมการแก้ไข; ไซต์การโทรจะถูกละเว้น สิ่งนี้มีความหมายบางอย่าง: พารามิเตอร์ไม่ได้รับการประเมินและมีเงื่อนไขเงื่อนไข, ไม่มีการแก้ไข, ในผลลัพธ์ของคอมไพเลอร์ คุณสามารถตรวจสอบได้ด้วยการสะท้อนกลับ msdn.microsoft.com/en-us/library/aa664622.aspx blogs.msdn.com/b/jmstall/archive/2007/10/15/…
ทำเครื่องหมาย Sowul

97

ฉันมักจะใช้DisplayName, DescriptionและDefaultValueคุณลักษณะคุณสมบัติของประชาชนมากกว่าการใช้งานของฉันควบคุมควบคุมที่กำหนดเองหรือระดับใด ๆ ฉันจะแก้ไขผ่านตารางทรัพย์สิน แท็กเหล่านี้ถูกใช้โดย. NET PropertyGrid เพื่อจัดรูปแบบชื่อพาเนลคำอธิบายและค่าตัวหนาที่ไม่ได้ตั้งค่าเป็นค่าเริ่มต้น

[DisplayName("Error color")]
[Description("The color used on nodes containing errors.")]
[DefaultValue(Color.Red)]
public Color ErrorColor
{
    ...
} 

ฉันแค่หวังว่า IntelliSense ของ Visual Studio จะคำนึงถึงDescriptionแอตทริบิวต์หากไม่พบความคิดเห็น XML มันจะหลีกเลี่ยงการต้องทำซ้ำประโยคเดิมสองครั้ง


3
ลาดเทเชื่อว่าไม่มีใครชี้ให้เห็นDescriptionจนกว่าคุณ .. มันเป็นประโยชน์มากที่สุดสำหรับฉันเมื่อใช้กับ enums ..
nawfal

68

[Serializable]ถูกใช้ตลอดเวลาสำหรับการซีเรียลไลซ์เซชั่นและการดีซีเรียลไลซ์ออบเจ็กต์ไปยังและจากแหล่งข้อมูลภายนอกเช่น xml หรือจากเซิร์ฟเวอร์ระยะไกล เพิ่มเติมเกี่ยวกับที่นี่


จริงๆแล้วมันถูกอ้างถึง psuedoattribute เนื่องจาก C # ปล่อยแฟล็ก metadata สำหรับ [Serializable] ไม่ใช่อินสแตนซ์ของแอตทริบิวต์ที่กำหนดเอง;)
TraumaPony

1
ในขณะที่มีประโยชน์มาก [Serializable] อยู่ไกลจากความสมบูรณ์แบบ ต้องใช้วิธีแก้ไขและทดลองและข้อผิดพลาดมากเกินไปเพื่อให้ได้ผลลัพธ์ที่คุณต้องการ
shoosh

ฉันจะรอง shoosh ที่สอง!
John Bubriski

System.NonSerializedAttribute มีประโยชน์หากคุณต้องการควบคุมการทำให้เป็นอันดับอัตโนมัติมากขึ้น
CSharper

ในฐานะที่เป็นบันทึกด้านข้างฉันจะเพิ่มว่าประสิทธิภาพการทำงานของการจัดลำดับ. Net ในตัวนั้นค่อนข้างแย่เช่น 2 หรือ 3 คำสั่งของขนาดที่ช้ากว่าโค้ดที่สร้างขึ้นด้วยมือ
redcalx

57

ในวิญญาณของฮอฟสตัดท์[Attribute]แอตทริบิวต์นั้นมีประโยชน์มากเพราะเป็นวิธีที่คุณสร้างคุณลักษณะของคุณเอง ฉันใช้คุณลักษณะแทนอินเทอร์เฟซเพื่อใช้ระบบปลั๊กอินเพิ่มคำอธิบายให้กับ Enums จำลองการกระจายหลายแบบและเทคนิคอื่น ๆ


13
ฟังดูดีนะ! คุณจะแสดงตัวอย่างของระบบปลั๊กอินและคำอธิบาย enum หรือไม่? นี่เป็นทั้งสองสิ่งที่ฉันสนใจที่จะนำไปใช้!
John Bubriski

46

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


7
คุณไม่ได้หมายความว่ามีประโยชน์ในการแฮ็คการทดสอบหน่วยในสิ่งที่ไม่สามารถ / ไม่ควรทำการทดสอบใช่ไหม
the_drow

@the_drow: คุณพูดถึง 'private accessors': msdn.microsoft.com/en-us/library/ms184807%28v=vs.80%29.aspx
habakuk

@habakuk: ไม่จริง มีหลายกรณีที่ควรเปิดชั้นเรียนภายในสำหรับการทดสอบหน่วยซึ่งมักจะเกิดจากการออกแบบที่ไม่ดี
the_drow

2
@The_drow: ฉันจะไม่พูดว่า InternalsVisibleTo เป็นสิ่งที่เลวร้ายสำหรับการทดสอบหน่วย คุณสามารถสร้างและทดสอบ "หน่วย" ที่เล็กกว่าซึ่งไม่สามารถมองเห็นได้นอกโครงการของคุณ (ช่วยให้คุณมี API ที่สะอาดและเล็ก) แต่ถ้าคุณต้องการ 'ผู้เข้าถึงส่วนตัว' ในการทดสอบบางสิ่งบางอย่างอาจมีบางอย่างผิดปกติ
habakuk

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


28

ฉันแนะนำ[TestFixture]และ[Test]- จากห้องสมุดnUnit

การทดสอบหน่วยในรหัสของคุณให้ความปลอดภัยในการเปลี่ยนโครงสร้างและจัดทำเอกสาร


26
[XmlIgnore]

เช่นนี้ช่วยให้คุณสามารถละเว้น (ใน xml ใด ๆ อนุกรม) วัตถุ 'ผู้ปกครอง' ที่อาจก่อให้เกิดข้อยกเว้นเมื่อบันทึก


25

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

[ImmutableObject(true)]

6
ตามเอกสารที่ใช้ในเวลาออกแบบเท่านั้น (น่าเสียดายที่)
Hans Ke ในวันที่

1
เนื่องจากนี่เป็นเวลาออกแบบเท่านั้นอาจเป็นการดีกว่าที่จะสร้างImmutableObjectAttributeคลาสของคุณเอง- อย่างน้อยคุณก็สามารถกำจัดพารามิเตอร์ได้
Roy Tinker

25

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

class MyContextInformation : IDisposable {
    [ThreadStatic] private static MyContextInformation current;

    public static MyContextInformation Current {
        get { return current; }
    }

    private MyContextInformation previous;


    public MyContextInformation(Object myData) {
       this.myData = myData;
       previous = current;
       current = this;
    }

    public void Dispose() {
       current = previous;
    }
}

ต่อมาในรหัสของฉันฉันสามารถใช้สิ่งนี้เพื่อให้ข้อมูลเชิงบริบทนอกแถบให้ผู้คนดาวน์สตรีมจากรหัสของฉัน ตัวอย่าง:

using(new MyContextInformation(someInfoInContext)) {
   ...
}

แอตทริบิวต์ ThreadStatic อนุญาตให้ฉันกำหนดขอบเขตการโทรไปยังเธรดที่เป็นปัญหาเท่านั้นเพื่อหลีกเลี่ยงปัญหาความยุ่งเหยิงของการเข้าถึงข้อมูลข้ามเธรด


และวิธีการเข้าถึงแล้ว? ไม่เข้าใจจุดตัวอย่างการใช้งานของคุณที่นี่ คุณสามารถอธิบาย?
Beachwalker

@Beachwalker Current ควรเป็นแบบคงที่แก้ไขได้ทันที ตอนนี้คุณสามารถเข้าถึงMyContextInformation.Currentเพื่อรับบริบทที่ใช้งานอยู่บนสแต็ก นี่คือสิ่งที่เป็นแนวคิดที่ดีมากในบางกรณีเครื่องมือ (บริษัท ของฉัน) ของเราใช้มันเพื่อวัตถุประสงค์มากมาย
เฟลิกซ์เค

23

DebuggerHiddenAttributeซึ่งจะช่วยให้หลีกเลี่ยงขั้นตอนที่เป็นรหัสที่ไม่ควรบั๊ก

public static class CustomDebug
{
    [DebuggerHidden]
    public static void Assert(Boolean condition, Func<Exception> exceptionCreator) { ... }
}

...

// The following assert fails, and because of the attribute the exception is shown at this line
// Isn't affecting the stack trace
CustomDebug.Assert(false, () => new Exception()); 

นอกจากนี้ยังป้องกันไม่ให้แสดงวิธีในการติดตามสแต็กซึ่งมีประโยชน์เมื่อมีวิธีที่เพิ่งล้อมวิธีอื่น:

[DebuggerHidden]
public Element GetElementAt(Vector2 position)
{
    return GetElementAt(position.X, position.Y);
}

public Element GetElementAt(Single x, Single y) { ... }

หากคุณโทรGetElementAt(new Vector2(10, 10))และมีข้อผิดพลาดเกิดขึ้นที่วิธีการพันสายการโทรจะไม่แสดงวิธีการที่เรียกวิธีการที่พ่นข้อผิดพลาด


21

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

[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
public Foo Bar {
    get { return baz; }
    set { baz = value; }
}

4
มีประโยชน์มากสำหรับส่วนประกอบ WinForms ใช้ร่วมกับ [เรียกดูได้ (เท็จ)]
Mark Heath

3
จุดดี - [Browsable(false)]จำเป็นต้องซ่อนจากผู้ใช้ของนักออกแบบที่[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]จำเป็นเพื่อที่จะไม่ได้รับต่อเนื่อง
กำหนดค่า

17

มีเพียงไม่กี่แอททริบิวที่ได้รับการสนับสนุนคอมไพเลอร์ แต่การใช้แอททริบิวที่น่าสนใจอย่างหนึ่งคือใน AOP: PostSharpใช้แอททริบิวต์แบบ bespoke ของคุณเพื่อฉีด IL เข้าสู่วิธีการต่างๆ ... เป็นสิ่งที่ต้องการใช้งาน INotifyPropertyChanged อัตโนมัติ ( ที่นี่ )

สิ่งที่เกิดขึ้นและส่งผลกระทบต่อคอมไพเลอร์หรือรันไทม์โดยตรง :

  • [Conditional("FOO")] - การเรียกใช้เมธอดนี้ (รวมถึงการประเมินผลอาร์กิวเมนต์) จะเกิดขึ้นก็ต่อเมื่อมีการกำหนดสัญลักษณ์ "FOO" ระหว่างการสร้าง
  • [MethodImpl(...)] - ใช้เพื่อระบุบางสิ่งเช่นการซิงโครไนซ์การอินไลน์
  • [PrincipalPermission(...)] - ใช้ในการฉีดการตรวจสอบความปลอดภัยเข้าไปในรหัสโดยอัตโนมัติ
  • [TypeForwardedTo(...)]- ใช้เพื่อย้ายประเภทระหว่างแอสเซมบลีโดยไม่ต้องสร้างผู้เรียก

สำหรับสิ่งที่ตรวจสอบด้วยตนเองผ่านการสะท้อนกลับฉันเป็นแฟนตัวยงของSystem.ComponentModelคุณสมบัติ สิ่งที่ชอบ[TypeDescriptionProvider(...)], [TypeConverter(...)]และ[Editor(...)]ที่สมบูรณ์สามารถเปลี่ยนพฤติกรรมของประเภทในการผูกข้อมูลสถานการณ์ (เช่นคุณสมบัติแบบไดนามิก ฯลฯ )


15

ถ้าฉันจะทำการตระเวนรหัสครอบคลุมฉันคิดว่าทั้งสองจะด้านบน:

 [Serializable]
 [WebMethod]

15
[WebMethod] ใช้เพื่อตกแต่งวิธีการที่เปิดเผยในบริการเว็บ [อนุกรมได้] ทำเครื่องหมายวัตถุของคุณเพื่อให้พวกเขาสามารถต่อเนื่องเพื่อวัตถุประสงค์เช่นผ่านพวกเขาข้ามโดเมนแอ
Kev

15

ฉันได้ใช้[DataObjectMethod]เมื่อเร็ว ๆ นี้ มันอธิบายวิธีการเพื่อให้คุณสามารถใช้คลาสของคุณกับ ObjectDataSource (หรือตัวควบคุมอื่น ๆ )

[DataObjectMethod(DataObjectMethodType.Select)] 
[DataObjectMethod(DataObjectMethodType.Delete)] 
[DataObjectMethod(DataObjectMethodType.Update)] 
[DataObjectMethod(DataObjectMethodType.Insert)] 

ข้อมูลเพิ่มเติม


12

ในโครงการปัจจุบันของเราเราใช้

[ComVisible(false)]

ควบคุมความสามารถในการเข้าถึงของชนิดหรือสมาชิกที่ได้รับการจัดการแต่ละรายการหรือทุกประเภทภายในแอสเซมบลีเป็น COM

ข้อมูลเพิ่มเติม


12
[TypeConverter(typeof(ExpandableObjectConverter))]

บอกผู้ออกแบบให้ขยายคุณสมบัติซึ่งเป็นคลาส (ของการควบคุมของคุณ)

[Obfuscation]

สั่งให้เครื่องมือทำให้งงงวยเพื่อดำเนินการตามที่ระบุสำหรับแอสเซมบลีชนิดหรือสมาชิก (แม้ว่าโดยทั่วไปแล้วคุณจะใช้ระดับการประกอบ[assembly:ObfuscateAssemblyAttribute(true)]


1
ฉันเดา แต่ผิด แอ็ตทริบิวต์ Obfuscation เป็นเพียงคำแนะนำสำหรับผู้ที่ไม่เชื่อในบุคคลที่สาม ไม่ทำให้คอมไพเลอร์ทำให้งง ๆ โดยค่าเริ่มต้น
Dan Is Fiddling โดย Firelight

@DanNeely ฟรีสำหรับผู้ใช้ Visual Studio Pro / Ultimate!
Chris S

4
หากคุณอ้างถึง DotFuscator Community Edition ระดับการป้องกันจะมอบให้ต่ำที่สุดเท่าที่จะหาได้
Dan Is Fiddling โดย Firelight

@ricovox ฉันได้เพิ่มข้อมูลสรุป
Chris S

9

แอตทริบิวต์ที่ฉันใช้บ่อยที่สุดเป็นสิ่งที่เกี่ยวข้องกับ XML Serialization

XmlRoot

XmlElement

XmlAttribute

ฯลฯ ...

มีประโยชน์อย่างยิ่งเมื่อทำการแยกวิเคราะห์ XML อย่างรวดเร็วและสกปรก


8

เป็นนักพัฒนาระดับกลางที่ฉันชอบ

System.ComponentModel.EditorBrowsableAttribute อนุญาตให้ฉันซ่อนคุณสมบัติเพื่อให้ผู้พัฒนา UI ไม่ได้ถูกครอบงำด้วยคุณสมบัติที่ไม่จำเป็นต้องดู

System.ComponentModel.BindableAttributeบางสิ่งไม่จำเป็นต้องเป็นฐานข้อมูล อีกครั้งลดงานที่นักพัฒนา UI ต้องทำ

ฉันยังชอบDefaultValueที่ Lawrence Johnston พูดถึง

System.ComponentModel.BrowsableAttributeและFlagsมีการใช้อย่างสม่ำเสมอ

ฉันใช้ System.STAThreadAttribute System.ThreadStaticAttribute เมื่อจำเป็น

ยังไงซะ. ฉันเหล่านี้มีค่าเท่ากับสำหรับนักพัฒนากรอบงาน. Net ทั้งหมด


8

[EditorBrowsable(EditorBrowsableState.Never)]อนุญาตให้คุณซ่อนคุณสมบัติและวิธีการต่าง ๆ จาก IntelliSense หากโครงการไม่ได้อยู่ในโซลูชันของคุณ มีประโยชน์มากสำหรับการซ่อนการไหลที่ไม่ถูกต้องสำหรับส่วนต่อประสานที่คล่องแคล่ว คุณต้องการ GetHashCode () หรือ Equals () บ่อยแค่ไหน?

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


8

ฉันคิดว่าเป็นสิ่งสำคัญที่จะกล่าวถึงที่นี่ว่าคุณลักษณะต่อไปนี้เป็นสิ่งสำคัญเช่นกัน:

STAThreadAttribute 

ระบุว่าโมเดลเธรด COM สำหรับแอ็พพลิเคชันคือ apartment แบบเธรดเดียว (STA)

ตัวอย่างเช่นแอ็ตทริบิวต์นี้ถูกใช้ใน Windows Forms Applications:

static class Program
{
    /// <summary>
    /// The main entry point for the application.
    /// </summary>
    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new Form1());
    }
}

และนอกจากนี้ยังมี ...

SuppressMessageAttribute

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

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

[SuppressMessage("Microsoft.Performance", "CA1801:ReviewUnusedParameters", MessageId = "isChecked")]
[SuppressMessage("Microsoft.Performance", "CA1804:RemoveUnusedLocals", MessageId = "fileIdentifier")]
static void FileNode(string name, bool isChecked)
{
    string fileIdentifier = name;
    string fileName = name;
    string version = String.Empty;
}

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

7

นี่คือรายการด่วนเรียงลำดับคร่าวๆตามความถี่การใช้งานของคุณสมบัติที่กำหนดไว้ล่วงหน้าที่ฉันใช้จริงในโครงการขนาดใหญ่ (~ 500k LoCs):

ตั้งค่าสถานะ, Serializable, WebMethod, COMVisible, TypeConverter, แบบมีเงื่อนไข, ThreadStatic, ล้าสมัย, InternalsVisibleTo, DebuggerStepThrough


2
+1 สำหรับ ThreadStatic ไม่มีใครแปลกใจที่มีคนกล่าวว่าเพื่อให้ห่างไกลและยังสำหรับวิธีการทางสถิติ
staafl

6

ฉันสร้างคลาสเอนทิตีข้อมูลผ่าน CodeSmith และฉันใช้คุณลักษณะสำหรับรูทีนการตรวจสอบความถูกต้องบางอย่าง นี่คือตัวอย่าง:

/// <summary>
/// Firm ID
/// </summary>
[ChineseDescription("送样单位编号")]
[ValidRequired()]
public string FirmGUID
{
    get { return _firmGUID; }
    set { _firmGUID = value; }
}

และฉันได้รับคลาสยูทิลิตี้เพื่อทำการตรวจสอบตามคุณสมบัติที่แนบมากับคลาสเอนทิตีข้อมูล นี่คือรหัส:

namespace Reform.Water.Business.Common
{
/// <summary>
/// Validation Utility
/// </summary>
public static class ValidationUtility
{
    /// <summary>
    /// Data entity validation
    /// </summary>
    /// <param name="data">Data entity object</param>
    /// <returns>return true if the object is valid, otherwise return false</returns>
    public static bool Validate(object data)
    {
        bool result = true;
        PropertyInfo[] properties = data.GetType().GetProperties();
        foreach (PropertyInfo p in properties)
        {
            //Length validatioin
            Attribute attribute = Attribute.GetCustomAttribute(p,typeof(ValidLengthAttribute), false);
            if (attribute != null)
            {
                ValidLengthAttribute validLengthAttribute = attribute as ValidLengthAttribute;
                if (validLengthAttribute != null)
                {
                    int maxLength = validLengthAttribute.MaxLength;
                    int minLength = validLengthAttribute.MinLength;
                    string stringValue = p.GetValue(data, null).ToString();
                    if (stringValue.Length < minLength || stringValue.Length > maxLength)
                    {
                        return false;
                    }
                }
            }
            //Range validation
            attribute = Attribute.GetCustomAttribute(p,typeof(ValidRangeAttribute), false);
            if (attribute != null)
            {
                ValidRangeAttribute validRangeAttribute = attribute as ValidRangeAttribute;
                if (validRangeAttribute != null)
                {
                    decimal maxValue = decimal.MaxValue;
                    decimal minValue = decimal.MinValue;
                    decimal.TryParse(validRangeAttribute.MaxValueString, out maxValue);
                    decimal.TryParse(validRangeAttribute.MinValueString, out minValue);
                    decimal decimalValue = 0;
                    decimal.TryParse(p.GetValue(data, null).ToString(), out decimalValue);
                    if (decimalValue < minValue || decimalValue > maxValue)
                    {
                        return false;
                    }
                }
            }
            //Regex validation
            attribute = Attribute.GetCustomAttribute(p,typeof(ValidRegExAttribute), false);
            if (attribute != null)
            {
                ValidRegExAttribute validRegExAttribute = attribute as ValidRegExAttribute;
                if (validRegExAttribute != null)
                {
                    string objectStringValue = p.GetValue(data, null).ToString();
                    string regExString = validRegExAttribute.RegExString;
                    Regex regEx = new Regex(regExString);
                    if (regEx.Match(objectStringValue) == null)
                    {
                        return false;
                    }
                }
            }
            //Required field validation
            attribute = Attribute.GetCustomAttribute(p,typeof(ValidRequiredAttribute), false);
            if (attribute != null)
            {
                ValidRequiredAttribute validRequiredAttribute = attribute as ValidRequiredAttribute;
                if (validRequiredAttribute != null)
                {
                    object requiredPropertyValue = p.GetValue(data, null);
                    if (requiredPropertyValue == null || string.IsNullOrEmpty(requiredPropertyValue.ToString()))
                    {
                        return false;
                    }
                }
            }
        }
        return result;
    }
}
}


5

[System.Security.Permissions.PermissionSetAttribute] อนุญาตการดำเนินการด้านความปลอดภัยสำหรับ PermissionSet เพื่อนำไปใช้กับรหัสโดยใช้ความปลอดภัยที่เปิดเผย

// usage:
public class FullConditionUITypeEditor : UITypeEditor
{
    // The immediate caller is required to have been granted the FullTrust permission.
    [PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")]
    public FullConditionUITypeEditor() { }
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.