วิธีใดดีที่สุดในการจัดเก็บกลุ่มค่าคงที่ที่โปรแกรมของฉันใช้ [ปิด]


98

ฉันมีค่าคงที่ต่างๆที่ฉันใช้โปรแกรม ... string's,int s', double's ฯลฯ ... อะไรคือวิธีที่ดีที่สุดเพื่อเก็บพวกเขา? ฉันไม่คิดว่าฉันต้องการEnumเนื่องจากข้อมูลไม่ใช่ประเภทเดียวกันทั้งหมดและฉันต้องการตั้งค่าแต่ละค่าด้วยตนเอง ฉันควรเก็บทั้งหมดไว้ในชั้นเรียนที่ว่างเปล่าหรือไม่? หรือมีวิธีที่ดีกว่านี้?


18
ในแบบที่คุณต้องการ - นั่นคือวิธีที่คุณต้องการ
San Jacinto

คำตอบ:


136

คุณอาจมีอยู่ในคลาสแบบคงที่พร้อมคุณสมบัติอ่านอย่างเดียวแบบคงที่

public static class Routes
{
    public static string SignUp => "signup";
}

23
+1 แต่จะดีกว่าถ้าคุณสามารถดึงสิ่งเหล่านี้จากไฟล์ทรัพยากรเพื่อแปลเป็นภาษาท้องถิ่น
Joel Coehoorn

17
ดูเหมือนจะยุ่งยากนิดหน่อย - ทำไมไม่ใช้สตริงแบบอ่านอย่างเดียวแบบคงที่ล่ะ?
emptyset

6
ทำไมอ่านอย่างเดียวและไม่ใช่ const? คุณไม่ได้ตั้งค่าที่รันไทม์ดังนั้นจึงไม่จำเป็นต้องมีค่าเป็นแบบอ่านอย่างเดียว
Philip Wallace

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

13
ในฐานะผู้สนับสนุนของปีศาจฉันต้องชี้ให้เห็นว่าข้อได้เปรียบของ const คือคุณสามารถใช้มันในกรณีสลับได้
arviman

27

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

เมื่อฉันมี "ค่าคงที่" ที่ดึงเข้ามาจาก AppSettings หรือสิ่งที่คล้ายกันฉันจะยังคงมีคลาส "ค่าคงที่" ที่ตัดการอ่านจากตัวจัดการการกำหนดค่า มีความหมายมากกว่าที่จะมีConstants.SomeModule.Settingแทนที่จะต้องหันไปหาConfigurationManager.AppSettings["SomeModule/Setting"]สถานที่ใด ๆ ที่ต้องการใช้ค่าการตั้งค่าดังกล่าวโดยตรง

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


1
เพื่อเพิ่มสิ่งนี้: เหตุผลก็คือเมื่อคุณสร้างค่าคงที่ที่ใช้จากแอสเซมบลีอื่นจะไม่ได้รับการอัปเดต ซึ่งหมายความว่าหากคุณมี AssemblyA และ AssemblyB และ B ใช้ค่าคงที่จาก A ค่าจะถูกคัดลอกไม่ได้อ้างอิงดังนั้นการสร้าง A ใหม่จะไม่อัปเดต B ซึ่งอาจนำไปสู่ข้อบกพร่องแปลก ๆ
Camilo Martin

1
@CamiloMartin มีหลายวิธีในการจัดการกับสิ่งนั้น "ค่าคงที่" ของคุณอาจเป็นเพียงค่าคงที่อ่านอย่างเดียวเพื่อหลีกเลี่ยงสิ่งนั้นหรืออย่างที่ฉันบอกถ้าพวกเขาเปลี่ยนมากกว่าหนึ่งครั้งในดวงจันทร์สีน้ำเงินเพื่อใช้ ConfigurationManager
Chris Marisic

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

ปัญหาคือเมื่อคุณอ้างอิงแอสเซมบลีนี้จากแอสเซมบลีอื่นคุณจะต้องคัดลอกค่าลงในไฟล์กำหนดค่า
symbiont

@symbiont คุณสามารถฝังไฟล์กำหนดค่าและอ่านออกจากไฟล์ Manifest แทนได้หากต้องการสำหรับการแชร์เป็นองค์ประกอบของบุคคลที่สาม
Chris Marisic

19

สิ่งที่ฉันชอบทำมีดังต่อไปนี้ (แต่อย่าลืมอ่านจนจบเพื่อใช้ค่าคงที่ประเภทที่เหมาะสม):

internal static class ColumnKeys
{
    internal const string Date = "Date";
    internal const string Value = "Value";
    ...
}

อ่านสิ่งนี้เพื่อทราบว่าเหตุใดจึงconstอาจไม่ใช่สิ่งที่คุณต้องการ ประเภทของค่าคงที่ที่เป็นไปได้คือ:

  • constฟิลด์ อย่าใช้ข้ามแอสเซมบลี ( publicหรือprotected) หากค่าอาจเปลี่ยนแปลงในอนาคตเนื่องจากค่าจะถูกเข้ารหัสในเวลาคอมไพล์ในแอสเซมบลีอื่น ๆ หากคุณเปลี่ยนค่าค่าเดิมจะถูกใช้โดยแอสเซมบลีอื่น ๆ จนกว่าจะคอมไพล์ใหม่
  • static readonly ฟิลด์
  • static ทรัพย์สินที่ไม่มี set

1
ทำไมต้องอ่านอย่างเดียวถ้าใช้ในหลาย ๆ ส่วนประกอบ?
Philip Wallace

เหตุใดการอ่านอย่างเดียวแบบคงที่จึงทำงานได้ดีกว่ากับหลายชุดประกอบมากกว่า const
Matthew

15
ค่า Const ถูกคัดลอกจากแอสเซมบลีซอร์สลงในโค้ดที่คอมไพล์ ซึ่งหมายความว่าหากคุณต้องเปลี่ยนค่า const แอสเซมบลีที่อ้างอิงทั้งหมดจะต้องคอมไพล์ใหม่เทียบกับเวอร์ชันใหม่ ปลอดภัยและสะดวกกว่าในการใช้แบบอ่านอย่างเดียวแบบคงที่
cfeduke

6
ประโยชน์ของ const คือสามารถใช้ในสวิตช์
knaki02

11

นี่เป็นวิธีที่ดีที่สุด IMO ไม่จำเป็นต้องมีคุณสมบัติหรืออ่านอย่างเดียว:

public static class Constants
{
   public const string SomeConstant = "Some value";
}

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

4

คลาสคงที่ว่างมีความเหมาะสม พิจารณาใช้หลายคลาสเพื่อให้คุณได้กลุ่มค่าคงที่ที่เกี่ยวข้องที่ดีไม่ใช่ไฟล์ Globals.cs ขนาดยักษ์

นอกจากนี้สำหรับค่าคงที่ int ให้พิจารณาสัญกรณ์:

[Flags]
enum Foo
{
}

เนื่องจากสิ่งนี้ช่วยให้สามารถรักษาค่าเช่นแฟล็


"พิจารณาใช้หลาย ๆ คลาสเพื่อที่คุณจะได้กลุ่มของค่าคงที่ที่เกี่ยวข้องที่ดีไม่ใช่ไฟล์ Globals.cs ขนาดยักษ์" ฉันเชื่อว่านี่เป็นคำแนะนำที่ดีที่สุดไม่มีรูปแบบการออกแบบบางอย่างเกี่ยวกับเรื่องนี้? ฉันไม่รู้จักชื่อคุณ?
greg

3

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


2
สตริงการเชื่อมต่อไม่ใช่ค่าคงที่ แต่เป็นการตั้งค่า อาจเป็นไปได้ว่า OP ก็หมายถึงการตั้งค่าเช่นกันแทนที่จะเป็นค่าคงที่ แต่ฉันไม่เห็นหลักฐานใด ๆ
Jon Skeet

ฉันขอแตกต่าง ตัวอักษรสตริงคือค่าคงที่ตามนิยาม การเปลี่ยนสตริงในไฟล์กำหนดค่านั้นเทียบเท่ากับการเปลี่ยนในโค้ดและการคอมไพล์ใหม่ หากว่าที่ไม่ทำให้มันคงที่หรือไม่? ฉันไม่คิดอย่างนั้น
3Dave

2
@ เดวิด - ไม่จริง คอมไพเลอร์ไม่สนใจว่าคุณมีค่าอะไรในไฟล์กำหนดค่าของคุณซึ่งอ่านได้ที่รันไทม์
Philip Wallace

@PhilipW เข้าใจตรงกันนะ ประเด็นของฉันคือ (เพื่อตอบสนองต่อความคิดเห็นของ Jon Skeet) สตริงการเชื่อมต่อที่เฉพาะเจาะจงเป็นค่าคงที่เนื่องจากตัวอักษรสตริงทั้งหมดเป็น ความจริงที่ว่า "ค่าคงที่" สามารถเปลี่ยนแปลงได้ - ไม่ว่าจะเป็นการแก้ไขไฟล์ config และให้แอปของคุณดึงค่าใหม่จากไฟล์ config ดังกล่าวหรือโดยการเปลี่ยนลิเทอรัลในโค้ดซึ่งจะต้องมีการคอมไพล์ใหม่ / ปรับใช้ - ไม่ ทำให้เป็น "การตั้งค่า" สตริงเองจะคงที่โดยไม่คำนึงถึงคอนเทนเนอร์ ฉันเข้าใจและเห็นด้วยกับประเด็นของคุณ - มันไม่ใช่สิ่งที่ฉันพูด
3Dave

1
จากประสบการณ์ของฉัน ณ จุดหนึ่งในอนาคตที่ไม่คาดฝันค่า "คงที่" ของคุณจะต้องเปลี่ยนไปแม้ว่าคุณจะคิดว่ามันจะไม่มีวันเกิดขึ้นในอีกล้านปีก็ตาม ฉันคิดว่าสิ่งนี้ทำได้ง่ายกว่าในไฟล์. config มากกว่าการเปลี่ยนซอร์สโค้ด ทุกอย่างจบลงด้วยการตั้งค่าในที่สุด
NinjaBomb

1

ใช่static classสำหรับการจัดเก็บค่าคงที่จะใช้ได้ดียกเว้นค่าคงที่ที่เกี่ยวข้องกับประเภทเฉพาะ


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

0

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

Properties.Settings.Default.ServiceRef

0

ฉันขอแนะนำคลาสแบบคงที่แบบอ่านอย่างเดียวแบบคงที่ โปรดดูข้อมูลโค้ดด้านล่าง:

  public static class CachedKeysManager
    {
        public static readonly string DistributorList = "distributorList";
    }
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.