Apa cara terbaik untuk menyimpan sekelompok konstanta yang digunakan program saya? [Tutup]

97

Saya memiliki berbagai konstanta yang digunakan program saya ... string's, int' s, double's, dll ... Apa cara terbaik untuk menyimpannya? Saya tidak berpikir saya menginginkannya Enum, karena datanya tidak semua jenis yang sama, dan saya ingin mengatur setiap nilai secara manual. Haruskah saya menyimpan semuanya di kelas kosong? Atau apakah ada cara yang lebih baik?

Matthew
sumber
18
Apa pun yang Anda inginkan - begitulah cara Anda membutuhkannya.
San Jacinto

Jawaban:

135

Anda mungkin dapat memilikinya dalam kelas statis, dengan properti hanya baca statis.

public static class Routes
{
    public static string SignUp => "signup";
}
Daniel A. White
sumber
23
+1, tetapi lebih baik lagi jika Anda dapat mengambilnya dari file sumber daya untuk pelokalan.
Joel Coehoorn
17
Tampaknya sedikit bertele-tele - mengapa tidak string hanya baca statis?
emptyset
6
Mengapa readonly dan bukan const? Anda tidak menyetel nilai pada waktu proses, jadi tidak perlu menjadikannya hanya-baca.
Philip Wallace
91
Masalah dengan const adalah bahwa setiap assemblies yang dikompilasi terhadap const mendapatkan salinan lokal dari const tersebut ketika mereka sendiri dikompilasi; jadi jika Anda mengubah nilai, Anda juga harus mengkompilasi ulang semua rakitan yang bergantung pada rakitan Anda yang mendefinisikan konstanta - oleh karena itu sering kali lebih aman menggunakan rute hanya-baca. Properti alih-alih nilai statis publik memberi Anda fleksibilitas untuk menambahkan beberapa logika pemrograman di masa mendatang jika Anda membutuhkannya (yaitu membaca dari lokalisasi) tanpa mengubah antarmuka ke nilai konstan Anda.
cfeduke
11
Sebagai penganjur iblis, saya harus menunjukkan bahwa keuntungan dengan const adalah Anda dapat menggunakannya dalam kasus peralihan.
arviman
27

IMO menggunakan kelas yang penuh dengan konstanta tidak masalah untuk konstanta. Jika mereka akan berubah semi-sesekali, saya sarankan menggunakan AppSettings di config Anda dan kelas ConfigurationManager sebagai gantinya.

Ketika saya memiliki "konstanta" yang benar-benar ditarik dari AppSettings atau serupa, saya masih akan selalu memiliki kelas "konstanta" yang membungkus pembacaan dari manajer konfigurasi. Itu selalu lebih bermakna untuk dimiliki Constants.SomeModule.Settingdaripada harus langsung pergi ke ConfigurationManager.AppSettings["SomeModule/Setting"]tempat mana pun yang ingin mengkonsumsi nilai pengaturan tersebut.

Poin bonus untuk penyiapan ini, karena SomeModulekemungkinan akan menjadi kelas bersarang di dalam file Constants, Anda dapat dengan mudah menggunakan Injeksi Ketergantungan untuk menyuntikkan SomeModulelangsung ke kelas yang bergantung padanya. Anda juga dapat mengekstrak antarmuka di atas SomeModuledan kemudian membuat ketergantungan ke ISomeModuleConfigurationdalam kode konsumsi Anda, ini kemudian akan memungkinkan Anda untuk memisahkan ketergantungan ke file Constants, dan bahkan berpotensi membuat pengujian lebih mudah, terutama jika pengaturan ini berasal dari AppSettings dan Anda mengubahnya menggunakan transformasi konfigurasi karena pengaturannya khusus lingkungan.

Chris Marisic
sumber
1
Hanya untuk menambahkan ini: alasannya adalah ketika Anda membangun, konstanta yang digunakan dari rakitan lain tidak diperbarui. Ini berarti bahwa jika Anda memiliki AssemblyA dan AssemblyB dan B menggunakan konstanta dari A, nilainya disalin, tidak direferensikan, jadi membangun ulang A tidak akan memperbarui B. Hal ini dapat menyebabkan bug aneh.
Camilo Martin
1
@CamiloMartin banyak cara untuk mengatasinya, "konstanta" Anda hanya dapat dibaca secara statis untuk menghindarinya, atau seperti yang saya katakan jika mereka berubah lebih dari sekali dalam bulan biru untuk menggunakan Pengelola Konfigurasi.
Chris Marisic
Ya, saya baru saja mengatakan bahwa ini bukan hanya karena ini adalah konvensi bahwa Anda harus menggunakan statis hanya baca, tetapi karena ini sebenarnya dapat menjadi sumber kebingungan. Selain itu, alternatif dari ConfigurationManager adalah file sumber daya - Anda hanya perlu menambahkan file sumber daya lain dengan kode bahasa di namanya dan kode Anda langsung dilokalkan.
Camilo Martin
masalahnya adalah ketika Anda mereferensikan rakitan ini dari rakitan lain, Anda harus menyalin nilai ke dalam file konfigurasinya
symbiont
@symbiont Anda dapat menyematkan file konfigurasi dan membacanya dari manifes jika Anda mau, agar dapat dibagikan sebagai komponen pihak ketiga
Chris Marisic
19

Yang ingin saya lakukan adalah sebagai berikut (tetapi pastikan untuk membaca sampai akhir untuk menggunakan jenis konstanta yang tepat ):

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

Baca ini untuk mengetahui mengapa constmungkin bukan yang Anda inginkan. Kemungkinan jenis konstanta adalah:

  • constbidang. Jangan gunakan di seluruh rakitan ( publicatau protected) jika nilai mungkin berubah di masa mendatang karena nilai akan di-hardcode pada waktu kompilasi di rakitan lain tersebut. Jika Anda mengubah nilainya, nilai lama akan digunakan oleh rakitan lain sampai mereka dikompilasi ulang.
  • static readonly bidang
  • static properti tanpa set
Marcel Gosselin
sumber
1
Mengapa hanya baca jika digunakan di banyak rakitan?
Philip Wallace
Mengapa hanya baca statis berfungsi lebih baik dengan beberapa rakitan daripada konst?
Matius
15
Nilai Const disalin dari rakitan sumber ke dalam kode yang dikompilasi. Ini berarti jika Anda harus mengubah nilai const, semua rakitan dependen HARUS dikompilasi ulang terhadap versi baru. Lebih aman dan nyaman digunakan hanya baca statis.
cfeduke
6
Manfaat dari const adalah dapat digunakan dalam sakelar
knaki02
11

Ini adalah cara terbaik IMO. Tidak perlu properti, atau hanya baca:

public static class Constants
{
   public const string SomeConstant = "Some value";
}
Philip Wallace
sumber
9
Jika Anda akan menggunakan const, ekspos hanya sebagai internal. Jangan jadikan konst publik (bahkan jika menurut Anda majelis Anda tidak akan digunakan di luar organisasi Anda). Properti juga memberi Anda fleksibilitas terprogram untuk perluasan di masa mendatang tanpa perlu menentukan ulang antarmuka Anda.
cfeduke
4

Kelas statis kosong sudah sesuai. Pertimbangkan untuk menggunakan beberapa kelas, sehingga Anda mendapatkan grup konstanta terkait yang bagus, dan bukan satu file Globals.cs raksasa.

Selain itu, untuk beberapa konstanta int, pertimbangkan notasinya:

[Flags]
enum Foo
{
}

Karena ini memungkinkan untuk memperlakukan nilai seperti bendera .

blankset
sumber
"Pertimbangkan untuk menggunakan beberapa kelas, sehingga Anda mendapatkan grup konstanta terkait yang bagus, dan bukan satu file Globals.cs raksasa." Saya percaya ini adalah rekomendasi terbaik, bukankah ada beberapa pola desain di sekitar ini? Saya tidak tahu siapa pun yang namanya, bukan?
greg
3

Suara lain untuk menggunakan web.config atau app.config. File konfigurasi adalah tempat yang baik untuk konstanta seperti string koneksi, dll. Saya memilih untuk tidak melihat sumber untuk melihat atau memodifikasi jenis hal ini. Kelas statis yang membaca konstanta ini dari file .config mungkin merupakan kompromi yang baik, karena akan membiarkan aplikasi Anda mengakses sumber daya ini seolah-olah mereka didefinisikan dalam kode, tetapi tetap memberi Anda fleksibilitas untuk memilikinya dalam tampilan yang mudah dilihat / diedit ruang.

Simpan
sumber
2
String koneksi bukanlah konstanta, ini adalah pengaturan. Bisa jadi OP juga berarti pengaturan, bukan konstanta, tetapi saya tidak melihat bukti apa pun.
Jon Skeet
Saya mohon untuk berbeda. Literal string adalah konstanta menurut definisi. Mengubah string dalam file konfigurasi secara kasar sama dengan mengubahnya dalam kode dan kompilasi ulang; apakah itu akan membuatnya tidak konstan? Saya kira tidak.
Simpan 3
2
@David - Tidak benar. Kompilator tidak peduli tentang nilai apa yang Anda miliki di file konfigurasi - ini dibaca saat runtime.
Philip Wallace
@PhilipW Saya mengerti itu. Maksud saya adalah bahwa (sebagai tanggapan atas komentar Jon Skeet) string koneksi tertentu adalah sebuah konstanta, seperti halnya semua literal string. Fakta bahwa "konstanta" dapat diubah - baik dengan memodifikasi file konfigurasi, dan meminta aplikasi Anda menarik nilai baru dari file konfigurasi tersebut, atau dengan mengubah kode literal yang memerlukan kompilasi ulang / penerapan - tidak jadikan itu "pengaturan." String itu sendiri konstan, apa pun penampungnya. Saya mengerti dan setuju dengan maksud Anda - bukan itu yang saya katakan.
Simpan 3
1
Dalam pengalaman saya, pada suatu titik di masa depan yang tak terduga, nilai "konstan" Anda perlu berubah bahkan jika Anda mengira itu tidak akan pernah terjadi dalam sejuta tahun. Saya pikir ini jauh lebih mudah dilakukan dalam file .config daripada mengubah kode sumber. Semuanya akhirnya menjadi setting pada akhirnya.
NinjaBomb
1

Ya, static classkonstanta untuk menyimpan akan baik-baik saja, kecuali untuk konstanta yang terkait dengan tipe tertentu.

bruno conde
sumber
itulah yang saya coba lakukan. saya ingin mereka muncul sebagai anggota kelas tempat mereka berada. tetapi saya tidak ingin menambahkannya ke kelas karena konstanta bervariasi bergantung pada perusahaan tempat saya melakukan pekerjaan. saya belum menemukan apa pun tentang konstanta ekstensi atau properti. tetapi saya mungkin meninggalkan ide ini karena saya tidak ingin mereka muncul sebagai anggota ketika saya membuat serial kelas-kelas ini
symbiont
0

Jika Konstanta ini adalah referensi layanan atau sakelar yang mempengaruhi perilaku aplikasi, saya akan mengaturnya sebagai pengaturan pengguna Aplikasi. Dengan begitu, jika perlu diubah, Anda tidak perlu mengkompilasi ulang dan Anda masih bisa mereferensikannya melalui kelas properti statis.

Properties.Settings.Default.ServiceRef
Aaron
sumber
0

Saya akan menyarankan kelas statis dengan hanya baca statis. Silakan temukan cuplikan kode di bawah ini:

  public static class CachedKeysManager
    {
        public static readonly string DistributorList = "distributorList";
    }
KAPIL SHARMA
sumber