Apa yang dimaksud dengan CultureInfo.InvariantCulture?

178

Saya memiliki serangkaian teks seperti ini:

var foo = "FooBar";

Saya ingin mendeklarasikan string kedua yang dipanggil bardan menjadikannya sama dengan karakter pertama dan keempat dari karakter pertama saya foo, jadi saya melakukan ini seperti ini:

var bar = foo[0].ToString() + foo[3].ToString();

Ini berfungsi seperti yang diharapkan, tetapi ReSharper menyarankan saya untuk memasukkan Culture.InvariantCulturekurung saya, jadi baris ini berakhir seperti ini:

var bar = foo[0].ToString(CultureInfo.InvariantCulture)
        + foo[3].ToString(CultureInfo.InvariantCulture);

Apa artinya ini, dan apakah itu akan memengaruhi cara program saya berjalan?

JMK
sumber
2
Lihat pertanyaan SO ini: stackoverflow.com/questions/8492449/…
msigman
39
Bagi mereka yang mencari jawaban 5 detik: CultureInfo.InvariantCulture berarti "Saya tidak peduli, saya tidak ingin budaya terlibat di tempat pertama. Sekarang biarkan saya menggunakan hal bodoh."
Andrew
5
@ Andrew Bisakah Anda menulis ulang semua dokumen MS, pls?
Yatrix
3
@Yatrix Ya, tentu saja. Dengan senang hati! Siapa yang membayar
Andrew

Jawaban:

155

Tidak semua budaya menggunakan format yang sama untuk tanggal dan nilai desimal / mata uang.

Ini akan peduli untuk Anda ketika Anda mengkonversi nilai input (membaca) yang disimpan sebagai string untuk DateTime, float, doubleatau decimal. Juga penting jika Anda mencoba memformat tipe data tersebut ke string (tulis) untuk tampilan atau penyimpanan.

Jika Anda tahu budaya spesifik seperti apa tanggal dan nilai desimal / mata uang Anda sebelumnya, Anda dapat menggunakan CultureInfoproperti spesifik itu (yaitu CultureInfo("en-GB")). Misalnya jika Anda mengharapkan input pengguna.

The CultureInfo.InvariantCultureproperti digunakan jika Anda memformat atau parsing string yang harus diurai oleh software independen dari pengaturan lokal pengguna.

Nilai defaultnya CultureInfo.InstalledUICulturejadi CultureInfo default tergantung pada pengaturan OS yang mengeksekusi. Inilah sebabnya mengapa Anda harus selalu memastikan info budaya sesuai dengan niat Anda (lihat jawaban Martin untuk panduan yang baik).

JohnB
sumber
3
"id-AS", saya pikir itu mungkin benar-benar tergantung pada pengaturan sistem Anda.
Tracker1
44
Nilai standarnya bukan en-US. Ini budaya lokal. Dan InvariantCulturedigunakan ketika Anda ingin memformat netral budaya yang independen dari sistem lokal. Misalnya ketika bekerja dengan format file berbasis teks.
CodesInChaos
23
Untuk menambahkan komentar @CodesInChaos: Klaim bahwa nilai default adalah CultureInfo ("en-US") salah. Juga, pernyataan Properti CultureInfo.InvariantCulture digunakan ketika Anda tidak yakin sebelumnya apa budaya memformat tanggal dan nilai desimal / mata uang Anda. Membingungkan. Baik menggunakan arus, invarian atau budaya tertentu adalah sesuatu yang harus menjadi keputusan sadar, dan jika Anda salah Anda dapat mengasingkan pengguna (non-AS) Anda. Anda seharusnya tidak menggunakan budaya invarian jika Anda "tidak yakin". Anda harus yakin sebelumnya.
Martin Liversage
3
-1 karena masalah yang disebutkan dalam komentar lain. Jawaban oleh Martin lebih membantu karena memberi tahu Anda kapan harus menggunakan dan tidak menggunakan setiap budaya.
Ed Greaves
"jika Anda bekerja secara eksklusif dalam Bahasa Inggris Amerika, maka Anda tidak perlu khawatir tentang hal itu.": Salah, Anda mungkin bekerja secara eksklusif dalam Bahasa Inggris Amerika, tetapi perangkat lunak dapat berjalan pada "en-GB" atau "de" -DE "server, maka itu akan membuat perbedaan, ditambah lagi dapat mengambil budaya klien (jika Anda mengatakannya di file web.config), dan itu mungkin bukan" en-US "...
Stefan Steiger
152

Ketika angka, tanggal dan waktu diformat menjadi string atau diurai dari string budaya digunakan untuk menentukan bagaimana hal itu dilakukan. Misalnya dalam en-USbudaya dominan Anda memiliki representasi string ini:

  • 1.000.000,00 - satu juta dengan fraksi dua digit
  • 1/29/2013 - tanggal posting ini

Dalam budaya saya ( da-DK) nilai memiliki representasi string ini:

  • 1.000.000,00 - satu juta dengan pecahan dua digit
  • 29-01-2013 - tanggal posting ini

Dalam sistem operasi Windows, pengguna bahkan dapat menyesuaikan bagaimana angka dan tanggal / waktu diformat dan juga dapat memilih budaya lain selain budaya sistem operasinya. Format yang digunakan adalah pilihan pengguna yang seharusnya.

Jadi ketika Anda memformat nilai yang akan ditampilkan kepada pengguna menggunakan misalnya ToStringatau String.Formatatau diuraikan dari string menggunakan DateTime.Parseatau Decimal.Parsedefaultnya adalah menggunakan CultureInfo.CurrentCulture. Ini memungkinkan pengguna untuk mengontrol pemformatan.

Namun, banyak pemformatan string dan parsing sebenarnya bukan string yang dipertukarkan antara aplikasi dan pengguna tetapi antara aplikasi dan beberapa format data (misalnya file XML atau CSV). Dalam hal ini Anda tidak ingin menggunakan CultureInfo.CurrentCulturekarena jika pemformatan dan penguraian dilakukan dengan budaya yang berbeda, itu bisa rusak. Dalam hal ini Anda ingin menggunakan CultureInfo.InvariantCulture(yang didasarkan pada en-USbudaya). Ini memastikan bahwa nilai-nilai dapat bolak-balik tanpa masalah.

Alasan bahwa ReSharper memberikan peringatan adalah bahwa beberapa penulis aplikasi tidak menyadari perbedaan ini yang dapat menyebabkan hasil yang tidak diinginkan tetapi mereka tidak pernah menemukan ini karena mereka CultureInfo.CurrentCultureyaitu en-USyang memiliki perilaku yang sama dengan CultureInfo.InvariantCulture. Namun, segera setelah aplikasi digunakan dalam budaya lain di mana ada kemungkinan menggunakan satu budaya untuk memformat dan yang lain untuk mem-parsing aplikasi mungkin rusak.

Jadi untuk meringkasnya:

  • Gunakan CultureInfo.CurrentCulture(default) jika Anda memformat atau mem-parsing string pengguna.
  • Gunakan CultureInfo.InvariantCulturejika Anda memformat atau mem-parsing string yang seharusnya dapat diuraikan oleh perangkat lunak.
  • Jarang menggunakan budaya nasional tertentu karena pengguna tidak dapat mengontrol bagaimana pemformatan dan penguraian dilakukan.
Martin Liversage
sumber
1
Sehubungan dengan poin terakhir, "Jarang menggunakan budaya nasional tertentu ...", akankah format mata uang menjadi pengecualian? Misalnya, jika saya memiliki Decimalvariabel yang berisi nilai tertentu dalam Dolar AS, apakah saya ingin membuat pengecualian dan menggunakan en-USsebagai budaya saat menampilkannya untuk memastikan saya tidak mendapatkan hasil yang terlihat seperti angka dalam Euro? Saya mencoba CultureInfo.InvariantCulture , tetapi mendapatkan ini untuk penanda mata uang ¤, jadi saya tidak yakin itu cara yang benar.
Jeff B
1
@JeffBridgman: Saran saya hanya saran umum dan mungkin tidak berlaku untuk kasus spesifik Anda. Namun, saya akan berpikir bahwa cara Anda menampilkan titik desimal (koma atau titik) harus menjadi sesuatu yang dikontrol pengguna (misalnya penggunaan CultureInfo.CurrentCulture). Jika Anda selain menampilkan angka memerlukan mata uang maka mungkin Anda harus melakukannya secara konsisten, yaitu tidak menggunakan CultureInfodan sebaliknya menggunakan kode mata uang tiga huruf seperti USD 1,234.56. Maka Anda tidak masuk ke masalah pemetaan mata uang ke budaya.
Martin Liversage
26

Menurut Microsoft:

Properti CultureInfo.InvariantCulture bukan netral atau budaya tertentu. Ini adalah jenis budaya ketiga yang tidak sensitif terhadap budaya. Bahasa ini dikaitkan dengan bahasa Inggris tetapi tidak dengan negara atau wilayah.

(dari http://msdn.microsoft.com/en-us/library/4c5zdc6a(vs.71).aspx )

Jadi InvariantCulture mirip dengan budaya "en-US" tetapi tidak persis sama. Jika Anda menulis:

var d = DateTime.Now;
var s1 = d.ToString(CultureInfo.InvariantCulture);   // "05/21/2014 22:09:28"
var s2 = d.ToString(new CultureInfo("en-US"));       // "5/21/2014 10:09:28 PM"

kemudian s1 dan s2 akan memiliki format similair tetapi InvariantCulture menambahkan nol terkemuka dan "en-US" menggunakan AM atau PM.

Jadi InvariantCulture lebih baik untuk penggunaan internal, ketika Anda misalnya menyimpan tanggal untuk file teks atau mem-parsing data. Dan CultureInfo yang ditentukan lebih baik ketika Anda menyajikan data (tanggal, mata uang ...) kepada pengguna akhir.

happybits
sumber
3
Saya menjalankan kode contoh Anda untuk mengonfirmasi: InvariantCulture menggunakan MM / dd / yyyy Amerika daripada mengikuti format ISO 8601 tahun berjalan pertama. Meskipun begitu, ini ditujukan untuk penyimpanan portabel dan pemrosesan mekanis, bukan untuk konsumsi manusia. Betapa membingungkan
Max Barraclough
4

Untuk hal-hal seperti angka (titik desimal, koma dalam jumlah), mereka biasanya lebih disukai dalam budaya tertentu.

Cara yang tepat untuk melakukan ini adalah mengaturnya di tingkat budaya (untuk Jerman) seperti ini:

Thread.CurrentThread.CurrentCulture.NumberFormat = new CultureInfo("de").NumberFormat;
Mesin Turing
sumber
4

JetBrains menawarkan penjelasan yang masuk akal ,

"Konversi ad-hoc dari struktur data ke teks sangat tergantung pada budaya saat ini, dan dapat menyebabkan hasil yang tidak diinginkan ketika kode dieksekusi pada mesin yang lokasinya berbeda dari pengembang asli. Untuk mencegah ambiguitas, ReSharper memperingatkan Anda tentang setiap contoh dalam kode di mana masalah tersebut dapat terjadi. "

tetapi jika saya mengerjakan situs yang saya tahu hanya berbahasa Inggris, saya mengabaikan saran itu.

Neil Thompson
sumber