从Linq Query异常中抛出异常

时间:2013-03-04 10:14:06

标签: c# linq exception

假设我有一个输入字符串,我需要格式化为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[]的范围并在float.Parse上格式化异常。这两个例外都会爆炸,对调用者来说绝对没有任何意义。

我知道我有两个解决方法(不使用像20世纪90年代那样的linq和循环或者抓住异常和重新打包),但是我想知道我是否能以某种方式向linq查询本身注入验证步骤以便在我检测到异常(pair.length<2pair[1]不是数字)?

3 个答案:

答案 0 :(得分: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方法。

(根据您使用的C#版本,您可能只使用.Select(ParsePair),但方法组转换和类型推断并不是最好的朋友。)

答案 1 :(得分:1)

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

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]));

答案 2 :(得分:0)

您可以先使用正则表达式

测试字符串
Regex r = new Regex(@"^((\w:\d);)*$");
bool test = r.IsMatch(tosplit);
相关问题