ความแตกต่างระหว่างconst
และreadonly
ใน C # คืออะไร?
เมื่อไหร่ที่คุณจะใช้อันอื่น
ความแตกต่างระหว่างconst
และreadonly
ใน C # คืออะไร?
เมื่อไหร่ที่คุณจะใช้อันอื่น
คำตอบ:
นอกเหนือจากความแตกต่างที่ชัดเจนของ
const
VS readonly
สามารถคำนวณแบบไดนามิก แต่ต้องได้รับการกำหนดก่อนที่นวกรรมิกจะออก .. หลังจากนั้นมันจะถูกแช่แข็งstatic
เป็นโดยปริยาย คุณใช้ClassName.ConstantName
สัญลักษณ์เพื่อเข้าถึงพวกเขามีความแตกต่างที่ลึกซึ้ง AssemblyA
พิจารณาระดับที่กำหนดไว้ใน
public class Const_V_Readonly
{
public const int I_CONST_VALUE = 2;
public readonly int I_RO_VALUE;
public Const_V_Readonly()
{
I_RO_VALUE = 3;
}
}
AssemblyB
การอ้างอิงAssemblyA
และใช้ค่าเหล่านี้ในรหัส เมื่อสิ่งนี้รวบรวม
const
ค่ามันก็เหมือนการค้นหาแทนที่ค่า 2 คือ 'อบเข้าสู่' AssemblyB
IL ซึ่งหมายความว่าหากในวันพรุ่งนี้ฉันจะอัปเดตI_CONST_VALUE
เป็น 20 ในอนาคต AssemblyB
ยังคงมี 2 จนฉัน recompile มันreadonly
ค่ามันเป็นเหมือนref
ที่ตั้งหน่วยความจำ ค่าไม่ได้ถูกอบเข้าสู่AssemblyB
IL ซึ่งหมายความว่าหากตำแหน่งหน่วยความจำถูกอัพเดตให้AssemblyB
รับค่าใหม่โดยไม่ต้องคอมไพล์ใหม่ ดังนั้นหากI_RO_VALUE
อัปเดตเป็น 30 คุณจะต้องสร้างAssemblyA
เท่านั้น ลูกค้าทั้งหมดไม่จำเป็นต้องทำการคอมไพล์ใหม่const
ดังนั้นถ้าคุณมีความมั่นใจว่าค่าคงที่จะไม่เปลี่ยนการใช้งาน
public const int CM_IN_A_METER = 100;
แต่ถ้าคุณมีอย่างต่อเนื่องที่อาจมีการเปลี่ยนแปลง (egwrt แม่นยำ) .. readonly
หรือเมื่อมีข้อสงสัยการใช้งาน
public readonly float PI = 3.14;
อัปเดต: Aku ต้องได้รับการกล่าวถึงเพราะเขาชี้ให้เห็นสิ่งนี้ก่อน นอกจากนี้ฉันต้องเสียบที่ฉันเรียนรู้สิ่งนี้ .. มีประสิทธิภาพ C # - Bill Wagner
static
จุดน่าจะเป็นจุดที่สำคัญที่สุดและมีประโยชน์ -consts are implicitly static
readonly
ตัวแปรสามารถเปลี่ยนแปลงได้นอกตัวสร้าง (การสะท้อน) มันเป็นเพียงคอมไพเลอร์ที่พยายามขัดขวางคุณจากการแก้ไข var นอกนวกรรมิก
readonly
ไม่อนุญาตให้เปลี่ยนตัวแปร@ mini-me เมื่อตัวสร้างสร้างเสร็จแม้ผ่านการสะท้อนกลับ รันไทม์เกิดขึ้นเพื่อไม่บังคับใช้ รันไทม์ยังเกิดขึ้นไม่ได้ในการบังคับใช้ที่คุณไม่ได้เปลี่ยนstring.Empty
ไป"Hello, world!"
แต่ฉันยังคงจะไม่เรียกร้องที่ว่านี้ทำให้string.Empty
สามารถปรับเปลี่ยนหรือรหัสที่ไม่ควรคิดว่าstring.Empty
จะเป็นสตริงความยาวเป็นศูนย์
มี gotcha พร้อม consts! หากคุณอ้างอิงค่าคงที่จากชุดประกอบอื่นค่าของมันจะถูกรวบรวมไว้ในชุดสายเรียก ด้วยวิธีนี้เมื่อคุณอัปเดตค่าคงที่ในแอสเซมบลีอ้างอิงมันจะไม่เปลี่ยนแปลงในแอสเซมบลีการเรียก!
เพียงเพื่อเพิ่ม ReadOnly สำหรับประเภทการอ้างอิงเท่านั้นทำให้การอ้างอิงไม่ใช่ค่าแบบอ่านอย่างเดียว ตัวอย่างเช่น:
public class Const_V_Readonly
{
public const int I_CONST_VALUE = 2;
public readonly char[] I_RO_VALUE = new Char[]{'a', 'b', 'c'};
public UpdateReadonly()
{
I_RO_VALUE[0] = 'V'; //perfectly legal and will update the value
I_RO_VALUE = new char[]{'V'}; //will cause compiler error
}
}
string
ที่คุณสามารถใช้เป็นค่าคงที่ได้หรือไม่?
const
ประเภทการอ้างอิงอื่นที่ไม่ใช่สตริง แต่ค่าคงที่สามารถมีค่าnull
ได้เท่านั้น
const
: ไม่สามารถเปลี่ยนแปลงได้ทุกที่
readonly
: ค่านี้สามารถเปลี่ยนแปลงได้ในตัวสร้างเท่านั้น ไม่สามารถเปลี่ยนแปลงได้ในฟังก์ชั่นปกติ
มี gotcha ขนาดเล็กพร้อมอ่านอย่างเดียว สามารถตั้งค่าฟิลด์แบบอ่านอย่างเดียวได้หลายครั้งภายในตัวสร้าง แม้ว่าค่าจะถูกตั้งค่าในตัวสร้างการโยงโซ่ที่แตกต่างกันสองตัวมันยังคงได้รับอนุญาต
public class Sample {
private readonly string ro;
public Sample() {
ro = "set";
}
public Sample(string value) : this() {
ro = value; // this works even though it was set in the no-arg ctor
}
}
สมาชิกคงที่จะถูกกำหนดในเวลารวบรวมและไม่สามารถเปลี่ยนแปลงได้ในขณะทำงาน ค่าคงที่จะประกาศเป็นฟิลด์โดยใช้const
คำหลักและต้องเริ่มต้นตามที่ประกาศไว้
public class MyClass
{
public const double PI1 = 3.14159;
}
readonly
สมาชิกเป็นเหมือนอย่างต่อเนื่องในการที่จะแสดงให้เห็นถึงความคุ้มค่าที่ไม่มีการเปลี่ยนแปลง ความแตกต่างคือreadonly
สมาชิกสามารถเริ่มต้นได้ที่รันไทม์ในตัวสร้างเช่นเดียวกับความสามารถในการเริ่มต้นตามที่พวกเขาจะประกาศ
public class MyClass1
{
public readonly double PI2 = 3.14159;
//or
public readonly double PI3;
public MyClass2()
{
PI3 = 3.14159;
}
}
const
static
(พวกเขาจะคงที่โดยปริยาย)อ่านเท่านั้น
static const int i = 0;
const
การประกาศไม่สามารถทำได้ภายในวิธี
const เป็นค่าคงที่เวลาคอมไพล์ในขณะที่อนุญาตให้คำนวณค่าแบบอ่านได้ในเวลารันไทม์และตั้งค่าในตัวสร้างหรือตัวกำหนดค่าเริ่มต้นของฟิลด์ ดังนั้น 'const' จึงเป็นค่าคงที่เสมอ แต่ 'readonly' จะเป็นแบบอ่านอย่างเดียวเมื่อถูกกำหนด
Eric Lippertจากทีม C # มีข้อมูลเพิ่มเติมเกี่ยวกับประเภทที่ไม่สามารถเปลี่ยนแปลงได้
นี่คือลิงค์อื่นที่แสดงว่า const ไม่ปลอดภัยหรือเกี่ยวข้องกับประเภทการอ้างอิง
สรุป :
อ่านอย่างเดียว : ค่าสามารถเปลี่ยนแปลงได้ผ่าน Ctor ตอนรันไทม์ แต่ไม่ผ่านฟังก์ชั่นสมาชิก
คงที่ : โดยดูถูกคงที่ ค่าไม่สามารถเปลี่ยนแปลงได้จากทุกที่ (Ctor, ฟังก์ชั่น, รันไทม์และอื่น ๆ ไม่มีที่)
อีก gotcha อื่น: ค่าแบบอ่านอย่างเดียวสามารถเปลี่ยนแปลงได้โดยรหัส "devious" ผ่านการสะท้อนกลับ
var fi = this.GetType()
.BaseType
.GetField("_someField",
BindingFlags.Instance | BindingFlags.NonPublic);
fi.SetValue(this, 1);
ฉันสามารถเปลี่ยนฟิลด์ที่สืบทอดแบบอ่านอย่างเดียวใน C # โดยใช้การสะท้อนได้หรือไม่?
ฉันเชื่อว่าconst
ค่าเหมือนกันสำหรับวัตถุทั้งหมด (และต้องเริ่มต้นด้วยการแสดงออกตามตัวอักษร) ในขณะที่readonly
สามารถแตกต่างกันสำหรับแต่ละ instantiation ...
สมาชิกในทีมหนึ่งคนในสำนักงานของเราได้ให้คำแนะนำต่อไปนี้เกี่ยวกับเวลาที่จะใช้ const, static และ readonly:
หมายเหตุสุดท้ายประการหนึ่ง: ฟิลด์ const เป็นค่าคงที่ แต่ค่าผกผันไม่เป็นความจริง
ทั้งสองเป็นค่าคงที่ แต่ const ยังมีอยู่ในเวลารวบรวม ซึ่งหมายความว่าแง่มุมหนึ่งของความแตกต่างคือคุณสามารถใช้ตัวแปร const เป็นอินพุตให้กับตัวสร้างแอ็ตทริบิวต์ แต่ไม่สามารถใช้ตัวแปรแบบอ่านอย่างเดียว
ตัวอย่าง:
public static class Text {
public const string ConstDescription = "This can be used.";
public readonly static string ReadonlyDescription = "Cannot be used.";
}
public class Foo
{
[Description(Text.ConstDescription)]
public int BarThatBuilds {
{ get; set; }
}
[Description(Text.ReadOnlyDescription)]
public int BarThatDoesNotBuild {
{ get; set; }
}
}
ควรใช้เมื่อใดconst
หรือreadonly
const
readonly
App.config
แต่เมื่อเริ่มต้นแล้วจะไม่สามารถเปลี่ยนแปลงได้ตัวแปรที่ทำเครื่องหมาย const นั้นเป็นแมโคร #define ที่พิมพ์ได้ดีกว่าเล็กน้อยในขณะรวบรวมการอ้างอิงตัวแปร const จะถูกแทนที่ด้วยค่าตามตัวอักษรแบบอินไลน์ ดังนั้นเฉพาะประเภทค่าดั้งเดิมบางชนิดเท่านั้นที่สามารถใช้วิธีนี้ได้ ตัวแปรที่ทำเครื่องหมายว่าอ่านได้อย่างเดียวสามารถตั้งค่าในตัวสร้างในเวลาทำงานและมีการบังคับใช้การอ่านอย่างเดียวในระหว่างเวลาทำงานเช่นกัน มีค่าใช้จ่ายประสิทธิภาพเล็กน้อยที่เกี่ยวข้องกับสิ่งนี้ แต่หมายความว่าคุณสามารถใช้แบบอ่านอย่างเดียวกับประเภทใด ๆ (แม้แต่ประเภทอ้างอิง)
นอกจากนี้ตัวแปร const จะเป็นแบบสแตติกโดยกำเนิดในขณะที่ตัวแปรแบบอ่านอย่างเดียวอาจเป็นอินสแตนซ์ที่เฉพาะเจาะจงหากต้องการ
อีกgotcha
เนื่องจาก const ใช้งานได้กับชนิดข้อมูลพื้นฐานเท่านั้นหากคุณต้องการทำงานกับคลาสคุณอาจรู้สึกว่า "ถูกบังคับ" ให้ใช้ ReadOnly อย่างไรก็ตามระวังกับดัก! อ่านอย่างเดียวหมายความว่าคุณไม่สามารถแทนที่วัตถุด้วยวัตถุอื่นได้ (คุณไม่สามารถอ้างถึงวัตถุอื่นได้) แต่กระบวนการใด ๆ ที่มีการอ้างอิงถึงวัตถุนั้นมีอิสระที่จะแก้ไขค่าภายในวัตถุ!
ดังนั้นอย่าสับสนกับการคิดว่า ReadOnly บอกเป็นนัยว่าผู้ใช้ไม่สามารถเปลี่ยนแปลงสิ่งต่างๆได้ ไม่มีไวยากรณ์ง่าย ๆ ใน C # เพื่อป้องกันการสร้างอินสแตนซ์ของคลาสจากการเปลี่ยนแปลงค่าภายใน (เท่าที่ฉันรู้)
const
จะต้องมีการกำหนดค่าตายตัวที่เป็นreadonly
สามารถตั้งค่าในการสร้างการเรียน
มีความแตกต่างที่โดดเด่นระหว่างเขตข้อมูล const และแบบอ่านอย่างเดียวใน C # .Net
const เป็นค่าคงที่เริ่มต้นและจะต้องเริ่มต้นด้วยค่าคงที่ซึ่งไม่สามารถแก้ไขได้ในภายหลัง ไม่อนุญาตให้เปลี่ยนแปลงค่าในตัวสร้างเช่นกัน มันไม่สามารถใช้กับประเภทข้อมูลทั้งหมด สำหรับอดีต DateTime มันไม่สามารถใช้กับประเภทข้อมูล DateTime
public const DateTime dt = DateTime.Today; //throws compilation error
public const string Name = string.Empty; //throws compilation error
public readonly string Name = string.Empty; //No error, legal
อ่านได้อย่างเดียวสามารถประกาศเป็นแบบคงที่ แต่ไม่จำเป็น ไม่จำเป็นต้องเริ่มต้น ณ เวลาที่ประกาศ ค่าสามารถกำหนดหรือเปลี่ยนแปลงได้โดยใช้ Constructor ดังนั้นจึงให้ประโยชน์เมื่อใช้เป็นสมาชิกคลาสอินสแตนซ์ การสร้างอินสแตนซ์ที่แตกต่างกันสองแบบอาจมีค่าของฟิลด์แบบอ่านอย่างเดียวแตกต่างกัน สำหรับอดีต -
class A
{
public readonly int Id;
public A(int i)
{
Id = i;
}
}
จากนั้นฟิลด์แบบอ่านอย่างเดียวสามารถเริ่มต้นได้ด้วยค่าเฉพาะทันทีดังนี้:
A objOne = new A(5);
A objTwo = new A(10);
ที่นี่อินสแตนซ์ objOne จะมีค่าของฟิลด์แบบอ่านอย่างเดียวเป็น 5 และ objTwo มี 10 ซึ่งไม่สามารถใช้ const
ค่าคงที่จะถูกรวบรวมเป็นคอนซูเมอร์เป็นค่าตัวอักษรในขณะที่สแตติกสตริงจะทำหน้าที่เป็นการอ้างอิงถึงค่าที่กำหนดไว้
ลองทำการสร้างไลบรารี่ภายนอกและใช้มันในแอพพลิเคชั่นคอนโซลจากนั้นเปลี่ยนค่าในไลบรารี่และทำการคอมไพล์ใหม่ (โดยไม่ต้องคอมไพล์โปรแกรมผู้บริโภค) จากนั้นปล่อย DLL ลงในไดเรกทอรีและเรียกใช้ EXE ด้วยตนเอง ที่สตริงคงที่จะไม่เปลี่ยนแปลง
คงที่
เราต้องระบุค่าให้กับฟิลด์ const เมื่อมันถูกกำหนด คอมไพเลอร์แล้วบันทึกค่าคงที่ในข้อมูลเมตาของแอสเซมบลี ซึ่งหมายความว่าค่าคงที่สามารถกำหนดได้เฉพาะสำหรับชนิดดั้งเดิมเช่นบูลีน, ถ่าน, ไบต์และอื่น ๆ ค่าคงที่ถือว่าเป็นสมาชิกแบบสแตติกเสมอไม่ใช่สมาชิกอินสแตนซ์
อ่านเท่านั้น
ฟิลด์แบบอ่านอย่างเดียวสามารถแก้ไขได้ที่รันไทม์ นั่นหมายความว่าเราสามารถกำหนดค่าสำหรับค่าโดยใช้ตัวสร้างสำหรับประเภทที่มีการประกาศเขตข้อมูล การตรวจสอบจะกระทำโดยคอมไพเลอร์ที่เขตข้อมูลแบบอ่านอย่างเดียวไม่ได้เขียนโดยวิธีการอื่นใดนอกจากตัวสร้าง
เพิ่มเติมเกี่ยวกับทั้งสองอธิบายไว้ที่นี่ในบทความนี้
โดยเฉพาะอย่างยิ่ง; คุณสามารถกำหนดค่าให้กับเขตข้อมูลแบบอ่านอย่างเดียวแบบคงที่ให้กับค่าที่ไม่คงที่ในขณะที่ค่าคงที่จะต้องกำหนดค่าคงที่
Const และอ่านอย่างเดียวมีความคล้ายคลึงกัน แต่ไม่เหมือนกันทุกประการ เขตข้อมูล const เป็นค่าคงที่เวลารวบรวมซึ่งหมายความว่าค่านั้นสามารถคำนวณได้ในเวลารวบรวม ฟิลด์แบบอ่านอย่างเดียวทำให้เกิดสถานการณ์เพิ่มเติมซึ่งต้องใช้รหัสบางอย่างระหว่างการสร้างประเภท หลังจากการก่อสร้างฟิลด์แบบอ่านอย่างเดียวไม่สามารถเปลี่ยนแปลงได้
ตัวอย่างเช่นสมาชิก const สามารถใช้เพื่อกำหนดสมาชิกเช่น:
struct Test
{
public const double Pi = 3.14;
public const int Zero = 0;
}
เนื่องจากค่าเช่น 3.14 และ 0 เป็นค่าคงที่เวลาคอมไพล์ อย่างไรก็ตามพิจารณากรณีที่คุณกำหนดประเภทและต้องการให้อินสแตนซ์ pre-fab บางอย่างของมัน ตัวอย่างเช่นคุณอาจต้องการกำหนดคลาสสีและให้ "ค่าคงที่" สำหรับสีทั่วไปเช่นสีดำสีขาว ฯลฯ คุณไม่สามารถทำสิ่งนี้กับสมาชิก const เนื่องจากด้านขวามือไม่ใช่ค่าคงที่เวลาคอมไพล์ หนึ่งสามารถทำได้กับสมาชิกคงที่ปกติ:
public class Color
{
public static Color Black = new Color(0, 0, 0);
public static Color White = new Color(255, 255, 255);
public static Color Red = new Color(255, 0, 0);
public static Color Green = new Color(0, 255, 0);
public static Color Blue = new Color(0, 0, 255);
private byte red, green, blue;
public Color(byte r, byte g, byte b) {
red = r;
green = g;
blue = b;
}
}
แต่ก็ไม่มีอะไรที่จะป้องกันไม่ให้ลูกค้าของสีจากการล้อเล่นกับมันบางทีโดยการเปลี่ยนค่าสีดำและสีขาว ไม่จำเป็นต้องพูดสิ่งนี้จะทำให้เกิดความหวาดกลัวสำหรับลูกค้ารายอื่น ๆ ของคลาสสี คุณลักษณะ "อ่านอย่างเดียว" กล่าวถึงสถานการณ์นี้ เพียงแค่แนะนำคำหลักแบบอ่านอย่างเดียวในการประกาศเราจะรักษาความยืดหยุ่นในการเริ่มต้นในขณะที่ป้องกันไม่ให้ลูกค้ารหัสการล้อเล่น
public class Color
{
public static readonly Color Black = new Color(0, 0, 0);
public static readonly Color White = new Color(255, 255, 255);
public static readonly Color Red = new Color(255, 0, 0);
public static readonly Color Green = new Color(0, 255, 0);
public static readonly Color Blue = new Color(0, 0, 255);
private byte red, green, blue;
public Color(byte r, byte g, byte b) {
red = r;
green = g;
blue = b;
}
}
เป็นที่น่าสนใจที่จะทราบว่าสมาชิก const มักจะคงที่ในขณะที่สมาชิกแบบอ่านอย่างเดียวอาจเป็นแบบคงที่หรือไม่เช่นเดียวกับเขตข้อมูลปกติ
เป็นไปได้ที่จะใช้คำหลักเดียวสำหรับสองวัตถุประสงค์นี้นำไปสู่ปัญหาการกำหนดเวอร์ชันหรือปัญหาประสิทธิภาพ สมมติว่าเราใช้คำหลักคำเดียวสำหรับ (const) นี้และผู้พัฒนาเขียน:
public class A
{
public static const C = 0;
}
และนักพัฒนาซอฟต์แวร์คนอื่นเขียนโค้ดที่ใช้ A:
public class B
{
static void Main() {
Console.WriteLine(A.C);
}
}
ตอนนี้โค้ดที่สร้างขึ้นสามารถขึ้นอยู่กับความจริงที่ว่า AC เป็นค่าคงที่เวลารวบรวมได้หรือไม่? คือสามารถใช้ AC แทนค่า 0 ได้หรือไม่? หากคุณพูดว่า "ใช่" นี่หมายความว่าผู้พัฒนา A ไม่สามารถเปลี่ยนวิธีการเริ่มต้น AC ได้ - สิ่งนี้จะอยู่ในมือของผู้พัฒนา A โดยไม่ได้รับอนุญาต หากคุณพูดว่า "ไม่" สำหรับคำถามนี้การเพิ่มประสิทธิภาพที่สำคัญจะพลาดไป บางทีผู้เขียน A อาจเป็นบวกว่า AC จะเป็นศูนย์เสมอ การใช้ทั้ง const และอ่านอย่างเดียวทำให้นักพัฒนา A สามารถระบุเจตนาได้ สิ่งนี้ทำให้เกิดพฤติกรรมการกำหนดเวอร์ชันที่ดีขึ้นและประสิทธิภาพที่ดีขึ้น
อ่านอย่างเดียว: ค่าจะเริ่มต้นได้เพียงครั้งเดียวจากตัวสร้างของคลาส
const: สามารถเริ่มต้นได้ในฟังก์ชั่นใด ๆ แต่เพียงครั้งเดียว
ความแตกต่างคือค่าของฟิลด์สแตติกแบบอ่านอย่างเดียวถูกตั้งค่า ณ รันไทม์ดังนั้นจึงสามารถมีค่าแตกต่างกันสำหรับการประมวลผลโปรแกรมที่แตกต่างกัน อย่างไรก็ตามค่าของฟิลด์ const ถูกตั้งค่าเป็นค่าคงที่เวลารวบรวม
เตือนความจำ: สำหรับประเภทการอ้างอิงทั้งสองกรณี (แบบคงที่และอินสแตนซ์) ตัวแก้ไขแบบอ่านอย่างเดียวจะป้องกันคุณจากการกำหนดการอ้างอิงใหม่ไปยังฟิลด์ มันไม่ได้ทำให้วัตถุที่ชี้โดยอ้างอิงไม่เปลี่ยนรูป
สำหรับรายละเอียดโปรดอ้างอิงคำถามที่พบบ่อย C # ในหัวข้อนี้: http://blogs.msdn.com/csharpfaq/archive/2004/12/03/274791.aspx
ตัวแปรคงที่จะประกาศและเริ่มต้น ณ เวลารวบรวม ค่าไม่สามารถเปลี่ยนแปลงได้หลังจากหอผู้ป่วย ตัวแปรแบบอ่านอย่างเดียวจะเริ่มต้นได้จากตัวสร้างสแตติกของคลาสเท่านั้น อ่านอย่างเดียวจะใช้เฉพาะเมื่อเราต้องการกำหนดค่าในขณะดำเนินการ
Const : ค่าคงที่ที่แน่นอนในช่วงอายุการใช้งาน
อ่านอย่างเดียว : สามารถเปลี่ยนแปลงได้ในเวลาทำงาน
สิ่งหนึ่งที่จะเพิ่มในสิ่งที่ผู้คนได้กล่าวไว้ข้างต้น หากคุณมีแอสเซมบลีที่ประกอบด้วยค่าแบบอ่านอย่างเดียว (เช่นอ่านอย่างเดียว MaxFooCount = 4;) คุณสามารถเปลี่ยนค่าที่เรียกแอสเซมบลีดูโดยส่งรุ่นใหม่ของแอสเซมบลีนั้นด้วยค่าที่แตกต่างกัน (เช่น MaxFooCount = 5
แต่ด้วย const มันจะถูกพับเป็นรหัสของผู้โทรเมื่อมีการรวบรวมผู้โทร
หากคุณมีความเชี่ยวชาญในระดับ C # ถึงระดับนี้คุณก็พร้อมสำหรับหนังสือของ Bill Wagner ที่มีประสิทธิภาพ C #: 50 วิธีเฉพาะในการปรับปรุง C # ของคุณซึ่งตอบคำถามนี้โดยละเอียด (และอีก 49 สิ่ง)