1

エントリのリストにフォーマットする必要がある入力文字列があるとしましょうKeyValuePair<string,float>。入力文字列の形式は次のとおりです。

key:value;key:value;...

それを行うためのこのLinqコードがあるとしましょう

var orr = from pco in (overrrides ?? string.Empty).Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries)
          let pair = pco.Split(new char[] { ':' }, StringSplitOptions.RemoveEmptyEntries)
          select new KeyValuePair<string, float>(pair[0], float.Parse(pair[1]));

ここで、入力文字列が適切にフォーマットされていない場合、linq は、範囲外のインデックスpair[]とフォーマット例外の 2 つの可能性のあるポイントで失敗しfloat.Parseます。これらの例外は両方ともボブルアップし、呼び出し元にはまったく意味がありません。

私は2つの回避策があることを知っています(1990年代のようにlinqとループを使用しないか、上記の例外を取得して再パッケージ化しないでください)、異常を検出した場合(pair.length<2またはpair[1]数ではない)?

4

3 に答える 3

3

簡単なオプションの 1 つは、次のように変更することです。

// I don't think I'd use ?? like this, but that's not the point of the question.
var unparsed = (overrrides ?? string.Empty).Split(new char[] { ';' }, 
                                                  StringSplitOptions.RemoveEmptyEntries);
var parsed = unparsed.Select(x => ParsePair(x));

...

static KeyValuePair<string, float> ParsePair(string text)
{
    // Note that you could be more efficient using IndexOf/Substring
    string[] bits = text.Split(new char[] { ':' }, StringSplitOptions.RemoveEmptyEntries);
    if (bits.Length != 2)
    {
        throw new ArgumentException("Value should be a colon-separated key/float pair");
    }
    float value;
    if (!float.TryParse(bits[1], out value))
    {
        throw new ArgumentException("Cannot parse " + bits[1] + " as a float");
    }
    return new KeyValuePair<string, float>(bits[0], value);
}

「シーケンス」部分にはまだLINQを使用しています。「単一の値を処理する方法」部分を別のメソッドに分割しているだけです。(大きなステートメント ラムダとして実行することもできParsePairますが、私はしません。) そうすることで、メソッドを個別にテストできることに注意してください。

.Select(ParsePair)(使用している C# のバージョンによっては、単に.

于 2013-03-04T10:22:30.607 に答える
1

throwステートメントとして、式lambdaで使用できないため、私が考えたことは不可能だと思います。唯一の方法は、副作用のある外部関数を作成し、それをすべてのエントリに適用するletorステートメントで実行することです。where

var pairIsValidOrDie = new Func<string[], bool>(pair => {
    float amt;
    if (pair.Length != 2 || !float.TryParse(pair[1], out amt)) throw new ArgumentException("ERROR: invalid price override string);
    return true;
});

var orr = from pco in (overrrides ?? string.Empty).Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries)
          let pair = pco.Split(new char[] { ':' }, StringSplitOptions.RemoveEmptyEntries)
          where pairIsValidOrDie(pair)
          select new KeyValuePair<string, float>(pair[0], float.Parse(pair[1]));
于 2013-03-04T10:55:25.373 に答える
0

最初に正規表現で文字列をテストできます

Regex r = new Regex(@"^((\w:\d);)*$");
bool test = r.IsMatch(tosplit);
于 2013-03-04T10:33:13.187 に答える