假设我有一个输入字符串,我需要格式化为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<2
或pair[1]
不是数字)?
答案 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中使用。唯一的方法是创建一个带有副作用的外部函数,并通过let
或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]));
答案 2 :(得分:0)
您可以先使用正则表达式
测试字符串Regex r = new Regex(@"^((\w:\d);)*$");
bool test = r.IsMatch(tosplit);