2009-12-12 22 views
6

Tôi cố gắng xử lý theo ký tự sau: ⨝ (http://www.fileformat.info/info/unicode/char/2a1d/index.htm)string.Empty.StartsWith (((char) 10781). ToString()) luôn trả về true?

Nếu bạn kiểm tra xem chuỗi rỗng có bắt đầu bằng ký tự này hay không, nó luôn trả về đúng, điều này không có ý nghĩa gì! Tại sao vậy?

// visual studio 2008 hides lines that have this char literally (bug in visual studio?!?) so i wrote it's unicode instead. 
char specialChar = (char)10781; 
string specialString = specialChar.ToString(); 

// prints 1 
Console.WriteLine(specialString.Length); 

// prints 10781 
Console.WriteLine((int)specialChar); 

// prints false 
Console.WriteLine(string.Empty.StartsWith("A")); 

// both prints true WTF?!? 
Console.WriteLine(string.Empty.StartsWith(specialString)); 
Console.WriteLine(string.Empty.StartsWith(((char)10781).ToString())); 

Trả lời

11

Bạn có thể sửa lỗi này bằng cách sử dụng ordinal StringComparison:

Từ các tài liệu MSDN:

Khi bạn chỉ định một trong hai StringComparison.Ordinal hoặc StringComparison.OrdinalIgnoreCase, so sánh chuỗi sẽ phi -linguistic. Tức là, các tính năng dành riêng cho ngôn ngữ tự nhiên bị bỏ qua khi thực hiện các quyết định so sánh . Điều này có nghĩa là quyết định dựa trên các byte đơn giản so sánh và bỏ qua vỏ hoặc các bảng tương đương được tham số hóa theo văn hóa. Kết quả là, bằng cách đặt thông số rõ ràng thành hoặc StringComparison.Ordinal hoặc StringComparison.OrdinalIgnoreCase, mã của bạn thường tăng tốc, tăng đúng và trở thành nhiều hơn đáng tin cậy.

char specialChar = (char)10781; 


    string specialString = Convert.ToString(specialChar); 

    // prints 1 
    Console.WriteLine(specialString.Length); 

    // prints 10781 
    Console.WriteLine((int)specialChar); 

    // prints false 
    Console.WriteLine(string.Empty.StartsWith("A")); 

    // prints false 
    Console.WriteLine(string.Empty.StartsWith(specialString, StringComparison.Ordinal)); 
+0

Văn hóa nhạy cảm-so sánh theo mặc định có vẻ giống như một vi phạm thảm họa lớn của nguyên tắc ít ngạc nhiên nhất. Có bất kỳ quy tắc nào để xác định phương pháp nào yêu cầu một StringComparison để có được hành vi thứ tự 'bình thường' hay không? – bobince

+0

@ bobince- bạn đã thấy câu hỏi này- http: // stackoverflow chưa.com/questions/72696/mà-thường-tốt nhất-to-sử dụng-stringcomparison-ordinalignorecase-hoặc-stringcom – RichardOD

4

đẹp unicode trục trặc ;-p

Tôi không chắc chắn lý do tại sao nó thực hiện điều này, nhưng amusingly:

Console.WriteLine(string.Empty.StartsWith(specialString)); // true 
Console.WriteLine(string.Empty.Contains(specialString)); // false 
Console.WriteLine("abc".StartsWith(specialString)); // true 
Console.WriteLine("abc".Contains(specialString)); // false 

Tôi đoán này được xử lý một chút như không tham gia ký tự Jon mentioned at devdays; một số chức năng chuỗi nhìn thấy nó, và một số thì không. Và nếu nó không nhìn thấy nó, điều này sẽ trở thành "không (một số chuỗi) bắt đầu với một chuỗi rỗng", đó là luôn luôn true.

+0

+1 từ tôi. Tôi đã không nhìn thấy cuộc nói chuyện của Jon. – RichardOD

4

Lý do cơ bản cho điều này là việc so sánh chuỗi mặc định là miền địa phương biết. Điều này có nghĩa là sử dụng các bảng dữ liệu địa phương để so sánh (bao gồm cả bình đẳng).

Nhiều (nếu không phải nhiều nhất) ký tự Unicode không có giá trị cho nhiều ngôn ngữ và do đó không tồn tại (hoặc làm, nhưng khớp với bất kỳ thứ gì hoặc không có gì).

Xem các mục nhập về trọng số ký tự trên blog của Michael Kaplan "Sorting It All Out". This series của các blog chứa rất nhiều thông tin cơ bản (các API có nguồn gốc, nhưng — như tôi hiểu — các cơ chế trong .NET giống nhau).

Phiên bản nhanh: đây là một khu vực phức tạp để có được sự so sánh (ngôn ngữ bình thường) mong đợi là khó, điều này có xu hướng dẫn đến những điều kỳ lạ với mã điểm cho glyphs bên ngoài ngôn ngữ của bạn.