10

代理ユニコード文字(非BMP、1文字あたり4バイト)を含む可能性のある文字列を使用しています。

\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")で機能しますが、一部は機能しません。

Q:これはF#のバグですか?F#を使用した文字列で許可されたサロゲートUnicode文字を処理するにはどうすればよいですか(F#の形式は異なりますか、それとも使用する方法のみです Char.ConvertFromUtf32 0x1D11E

更新:
s.ToCharArray() F#を提供し[| 0xD800; 0xDF41 |]ます; C#の場合{ 0xD834, 0xDD1E }

4

3 に答える 3

8

これは、VS2010(およびSP1)に付属しているF#コンパイラの既知のバグです。修正はVS11ビットに表示されるため、VS11ベータ版を使用していてF#3.0コンパイラを使用している場合は、これが期待どおりに動作することがわかります。

(ここにある他の回答/コメントが当面の間適切な回避策を提供しない場合は、私に知らせてください。)

于 2012-04-12T22:35:29.213 に答える
5

これは明らかに、F#がいくつかの文字列リテラルを解析しているときに間違いを犯すことを意味します。これは、あなたが言及した文字が非BMPであるという事実によって証明されており、UTF-16ではサロゲートのペアとして表される必要があります。サロゲートは0xD800-0xDFFFの範囲の単語ですが、生成された文字列の文字はどちらもその範囲に適合しません。

ただし、フレームワーク(内部にあるもの)は同じであるため、サロゲートの処理は変更されません。したがって、質問にはすでに答えがあります。コードにBMP以外の文字を含む文字列リテラルが必要な場合はChar.ConvertFromUtf32、\UXXXXXXXX表記の代わりに使用する必要があります。そして、残りのすべての処理はいつもとまったく同じになります。

于 2012-04-12T13:34:20.010 に答える
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以上です。

これがお役に立てば幸いです。

于 2012-04-12T13:23:01.897 に答える