2012-04-12 55 views
10

我正在處理字符串,它可能包含代理unicode字符(非BMP,每個字符4字節)。問題與代理unicode字符在F#

當我使用「\ Uxxxxxxxxv」格式在F#中指定代理字符時 - 對於某些字符,它給出的結果與C#不同。例如:

C#:

string s = "\U0001D11E"; 
bool c = Char.IsSurrogate(s, 0); 
Console.WriteLine(String.Format("Length: {0}, is surrogate: {1}", s.Length, c)); 

給出:Length: 2, is surrogate: True

F#:

let s = "\U0001D11E" 
let c = Char.IsSurrogate(s, 0) 
printf "Length: %d, is surrogate: %b" s.Length c 

給出:Length: 2, is surrogate: false

注意:有些替代字符在F#(「\ U0010011」,「\ U00100011」)中有效,但其中一些不起作用。

問:這是F#中的錯誤嗎?我該如何處理允許代理Unicode字符與F#的字符串(不F#有不同的格式,或僅方法是使用Char.ConvertFromUtf32 0x1D11E

更新:
s.ToCharArray()給出了F#[| 0xD800; 0xDF41 |]; for C#{ 0xD834, 0xDD1E }

+0

這些框架的方法,所以不要C#和F#之間的差異。 Quacks就像一個處理字符串文字的編譯器錯誤。記錄你從s.ToCharArray()中獲得的內容。 – 2012-04-12 13:12:59

+0

1)Char.IsSurrogate有2個簽名 - 第二個允許使用字符串和位置; 2)* let s ='\ U0001D11E'*導致編譯器錯誤 – Vitaliy 2012-04-12 13:20:05

回答

5

這顯然意味着F#在解析一些字符串文字時出錯。這已經被你提到的事實證明是非BMP的,在UTF-16中它應該被表示爲一對代理。 替代項是0xD800-0xDFFF範圍內的單詞,而生成的字符串中的字符都不適合該範圍。

但是代理的處理並沒有改變,因爲框架(引擎蓋下)是相同的。所以你的問題已經有了答案 - 如果你的代碼中需要帶有非BMP字符的字符串,你應該使用Char.ConvertFromUtf32而不是\ UXXXXXXXX表示法。其餘的處理過程將與往常一樣。

+0

謝謝,是的Char.ConvertFromUtf32可以用來作爲解決方案是一些情況下,它肯定是有限制的(我不能在常量中以這種方式聲明字符) – Vitaliy 2012-04-12 13:40:53

+0

您可以像這樣破解常量:''\ uD834 \ uDD1E'' 。這不是很可讀,可能最好添加評論來描述那是什麼,但最好還是不要。 – 2012-04-12 13:44:35

+0

謝謝 - 這將作爲解決方法 – Vitaliy 2012-04-12 13:45:52

1

在我看來,這是與不同形式的規範化相關的東西。 無論是在C#和F#s.IsNormalized()返回true 但在C#

s.ToCharArray()爲我們提供了{55348,56606} // 0xD834,0xDD1E

和F#

s.ToCharArray()爲我們提供了{65533,57422} // 0xFFFD,0xE04E

正如你可能知道System.Char.IsSurrogate是通過以下方式實現:

public static bool IsSurrogate(char c) 
    { 
     return (c >= HIGH_SURROGATE_START && c <= LOW_SURROGATE_END); 
    } 

其中

HIGH_SURROGATE_START = 0x00d800; 
    LOW_SURROGATE_END = 0x00dfff; 

所以在C#第一個字符(55348)小於LOW_SURROGATE_END但在F#第一個字符(65533)不大於LOW_SURROGATE_END以下。

我希望這會有所幫助。

+0

感謝您的問題描述,所以您認爲的問題是在F#中使用的不同規範化。好的,但是如果*「\ U0001D11E」*對我不起作用,我該如何使用F#將代理字符添加到字符串中? – Vitaliy 2012-04-12 13:29:44

+0

我不認爲這個問題與規範化有任何關係。實際上,像這樣的字符串應該被解析並按原樣呈現,這絕對是發生了什麼。 – 2012-04-12 13:54:58

7

這是VS2010(和SP1)附帶的F#編譯器中的一個已知錯誤;該修補程序出現在VS11位中,因此如果您有VS11 Beta並使用F#3.0編譯器,您會發現它的行爲與預期相同。

(如果其他的答案/評論這裏不爲您提供在此期間,一個合適的解決辦法,讓我知道。)

+0

謝謝 - 是的,@Andriy K的解決方案適用於我 – Vitaliy 2012-04-13 06:49:10