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 将在两个可能的点上失败,即 index out of range onpair[]和 format exception on float.Parse。这两个例外都会出现并且对调用者毫无意义。

我知道我有两种解决方法(不要像 1990 年代那样使用 linq 和循环,也不要抓住异常并重新打包),但是我想知道如果我检测到异常(pair.length<2pair[1]不是数字)?

4

3 回答 3

3

一个简单的选择是将其更改为:

// 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 用于“序列”部分 - 您只是将“如何处理单个值”部分分解为单独的方法。(您可以将它作为一个大语句 lambda,但我不会。)请注意,通过这样做,您可以ParsePair独立测试该方法。

.Select(ParsePair)(根据您使用的 C# 版本,您可能只使用 .

于 2013-03-04T10:22:30.607 回答
1

我想我想做的事情是不可能的throw,因为 as 语句不能在表达式 lambda 中使用。唯一的方法是创建一个具有副作用的外部函数,并通过letorwhere语句运行它,将其应用于每个条目。

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 回答