2012-03-18 74 views
118

Tôi có một chuỗi văn bản như sau:CultureInfo.InvariantCulture nghĩa là gì?

var foo = "FooBar"; 

Tôi muốn khai báo một chuỗi thứ hai gọi là bar và làm cho điều này tương đương với ký tự đầu tiên và thứ tư của foo đầu tiên của tôi, vì vậy tôi làm điều này như sau:

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

này hoạt động như mong đợi, nhưng ReSharper đang tư vấn cho tôi để đặt Culture.InvariantCulture bên trong dấu ngoặc tôi, vì vậy dòng này kết thúc như vậy:

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

Điều này có nghĩa là gì và nó có ảnh hưởng đến cách chương trình của tôi chạy không?

+1

Xem câu hỏi này SO: http://stackoverflow.com/questions/8492449/is- int32-tostring-culture-specific – msigman

+3

Đối với những người tìm kiếm câu trả lời 5 giây: CultureInfo.InvariantCulture có nghĩa là "Tôi không quan tâm, tôi không muốn văn hóa tham gia ngay từ đầu. Bây giờ hãy để tôi sử dụng điều ngu ngốc." – Andrew

Trả lời

94

Không phải tất cả các nền văn hóa đều sử dụng cùng định dạng cho ngày và giá trị thập phân/tiền tệ.

này sẽ quan trọng cho bạn khi bạn đang chuyển đổi đầu vào giá trị (đọc) được lưu trữ như dây đàn để DateTime, float, double hoặc decimal. Nó cũng sẽ quan trọng nếu bạn cố gắng định dạng các kiểu dữ liệu nói trên thành các chuỗi (viết) để hiển thị hoặc lưu trữ.

Nếu bạn biết văn hóa cụ thể nào mà ngày và giá trị thập phân/tiền tệ của bạn sẽ được đặt trước, bạn có thể sử dụng thuộc tính CultureInfo cụ thể đó (ví dụ: CultureInfo("en-GB")). Ví dụ: nếu bạn mong đợi đầu vào của người dùng.

Thuộc tính CultureInfo.InvariantCulture được sử dụng nếu bạn định dạng hoặc phân tích cú pháp chuỗi sẽ được phân tích cú pháp bằng một phần mềm độc lập với cài đặt cục bộ của người dùng.

Giá trị mặc định là CultureInfo.InstalledUICulture do đó CultureInfo mặc định phụ thuộc vào cài đặt của hệ điều hành thực thi. Đây là lý do tại sao bạn nên luôn đảm bảo thông tin văn hóa phù hợp với ý định của bạn (xem Martin's answer để có hướng dẫn tốt).

+3

"en-US" mặc dù, tôi nghĩ rằng nó thực sự có thể phụ thuộc vào cài đặt hệ thống của bạn. – Tracker1

+35

Giá trị mặc định không phải là 'en-US'. Đó là văn hóa địa phương. Và 'InvariantCulture' được sử dụng khi bạn muốn định dạng văn hóa trung lập độc lập với hệ thống cục bộ. Ví dụ: khi làm việc với các định dạng tệp dựa trên văn bản. – CodesInChaos

+14

Để thêm vào nhận xét @CodesInChaos: Xác nhận quyền sở hữu _Giá trị mặc định là CultureInfo ("en-US") _ đơn giản là sai. Ngoài ra, tuyên bố _The CultureInfo.InvariantCulture bất động sản được sử dụng khi bạn không chắc chắn trước thời gian định dạng văn hóa ngày của bạn và giá trị thập phân/tiền tệ sẽ được in._ là khó hiểu. Sử dụng một trong hai hiện tại, bất biến hoặc một nền văn hóa cụ thể là một cái gì đó mà nên là một quyết định có ý thức, và nếu bạn nhận được nó sai, bạn có thể xa lánh người dùng (không phải người Mỹ) của bạn. Bạn không nên sử dụng văn hóa bất biến nếu bạn "không chắc chắn". Bạn cần phải chắc chắn trước thời hạn. –

2

JetBrains cung cấp explanation hợp lý, nhưng nếu tôi đang làm việc trên trang web tôi biết sẽ chỉ có bằng tiếng Anh, tôi chỉ bỏ qua đề xuất.

94

Khi số, ngày tháng và thời gian được định dạng thành chuỗi hoặc phân tích cú pháp từ chuỗi một nền văn hóa được sử dụng để xác định như thế nào nó được thực hiện . Ví dụ. trong văn hóa chi phối en-US bạn có các biểu diễn chuỗi này:

  • 1.000.000.00 - một triệu với một phần nhỏ hai chữ số
  • 2013/01/29 - ngày này đăng

Trong văn hóa của tôi (da-DK) các giá trị có đại diện chuỗi này:

  • 1.000.000 , 00 - một triệu với một phần nhỏ hai chữ số
  • 29-01-2013 - ngày này đăng

trong hệ điều hành Windows người dùng thậm chí có thể tùy chỉnh cách số và ngày/giờ được định dạng và cũng có thể chọn một nền văn hóa khác so với văn hóa của hệ điều hành của mình. Định dạng được sử dụng là sự lựa chọn của người dùng đó là như thế nào.

Vì vậy, khi bạn định dạng một giá trị được hiển thị cho người dùng sử dụng ví dụ ToString hoặc String.Format hoặc phân tích cú pháp từ một chuỗi sử dụng DateTime.Parse hoặc Decimal.Parse mặc định là sử dụng CultureInfo.CurrentCulture. Điều này cho phép người dùng kiểm soát định dạng.

Tuy nhiên, rất nhiều định dạng chuỗi và phân tích cú pháp thực sự không phải là chuỗi trao đổi giữa ứng dụng và người dùng nhưng giữa ứng dụng và một số định dạng dữ liệu (ví dụ: tệp XML hoặc CSV). Trong trường hợp đó bạn không muốn sử dụng CultureInfo.CurrentCulture vì nếu định dạng và phân tích cú pháp được thực hiện với các nền văn hóa khác nhau, nó có thể phá vỡ. Trong trường hợp đó bạn muốn sử dụng CultureInfo.InvariantCulture (dựa trên văn bản en-US). Điều này đảm bảo rằng các giá trị có thể làm tròn mà không có vấn đề gì.

Lý do mà ReSharper mang đến cho bạn những cảnh báo là một số nhà văn ứng dụng không nhận thức được sự khác biệt này có thể dẫn đến kết quả ngoài ý muốn nhưng họ không bao giờ khám phá ra điều này bởi vì họ là CultureInfo.CurrentCultureen-US trong đó có các hành vi tương tự như CultureInfo.InvariantCulture. Tuy nhiên, ngay sau khi ứng dụng được sử dụng trong một nền văn hóa khác, nơi có khả năng sử dụng một nền văn bản để định dạng và một ứng dụng khác để phân tích ứng dụng có thể bị hỏng.

Vì vậy, để tóm tắt:

  • Sử dụng CultureInfo.CurrentCulture (mặc định) nếu bạn đang định dạng hoặc phân tích một chuỗi người dùng.
  • Sử dụng CultureInfo.InvariantCulture nếu bạn định dạng hoặc phân tích cú pháp chuỗi cần phân tích cú pháp bằng một phần mềm.
  • Hiếm khi sử dụng văn hóa quốc gia cụ thể vì người dùng không thể kiểm soát cách định dạng và phân tích cú pháp được thực hiện.
+0

Về điểm cuối cùng, "Hiếm khi sử dụng một nền văn hóa quốc gia cụ thể ...", định dạng tiền tệ có phải là ngoại lệ không? Ví dụ, nếu tôi có một biến 'thập phân' có chứa một giá trị nhất định bằng đô la Mỹ, tôi có muốn tạo một ngoại lệ và sử dụng' en-US' làm văn hóa khi hiển thị nó để đảm bảo rằng tôi không nhận được kết quả giống như một số bằng Euro? [Tôi đã cố gắng] (https://dotnetfiddle.net/WYpIvw) 'CultureInfo.InvariantCulture', nhưng có điều này cho các điểm đánh dấu tiền tệ' ¤', vì vậy tôi không chắc chắn đó là đúng cách. –

+1

@JeffBridgman: Lời khuyên của tôi chỉ là lời khuyên chung và có thể không áp dụng cho trường hợp cụ thể của bạn. Tuy nhiên, tôi nghĩ rằng cách bạn hiển thị dấu thập phân (dấu phẩy hoặc dấu chấm) phải là thứ mà người dùng kiểm soát (ví dụ: sử dụng 'CultureInfo.CurrentCulture'). Nếu bạn ngoài việc hiển thị một số cần tiền tệ thì có lẽ bạn nên làm điều đó một cách nhất quán, tức là không sử dụng 'CultureInfo' và thay vào đó sử dụng mã tiền tệ ba chữ cái như 'USD 1,234.56'. Sau đó, bạn không nhận được vào các vấn đề lập bản đồ một loại tiền tệ cho một nền văn hóa. –

17

Theo Microsoft:

Thuộc tính CultureInfo.InvariantCulture không phải là một trung tính hay một nền văn hóa cụ thể . Đây là loại hình văn hóa thứ ba là không nhạy cảm về văn hóa. Nó được liên kết với ngôn ngữ tiếng Anh nhưng không phải với quốc gia hoặc khu vực.

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

Vì vậy InvariantCulture là similair với văn hóa "en-US" nhưng không giống hệt nhau.Nếu bạn viết:

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" 

thì s1 và s2 sẽ có định dạng similair nhưng InvariantCulture thêm số 0 và "en-US" hàng đầu sử dụng AM hoặc PM.

Vì vậy, bất biến là tốt hơn cho việc sử dụng nội bộ, khi bạn ví dụ: lưu ngày vào tệp văn bản hoặc phân tích dữ liệu. Và một CultureInfo được chỉ định tốt hơn khi bạn trình bày dữ liệu (ngày, tiền tệ ...) cho người dùng cuối.

4

Đối với những thứ như số (dấu thập phân, dấu phẩy theo số lượng), chúng thường được ưu tiên trong văn hóa cụ thể.

Một cách thích hợp để làm điều này sẽ được thiết lập nó ở cấp độ văn hóa (đối với tiếng Đức) như thế này:

Thread.CurrentThread.CurrentCulture.NumberFormat = new CultureInfo("de").NumberFormat;