C# 从Linq查询异常引发异常
假设我有一个需要格式化为C# 从Linq查询异常引发异常,c#,linq,exception,C#,Linq,Exception,假设我有一个需要格式化为KeyValuePair条目列表的输入字符串。输入字符串的格式为 key:value;key:value;... 假设我有这个Linq代码来做 var orr = from pco in (overrrides ?? string.Empty).Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries) let pair = pco.Split(new char[] { ':' }
KeyValuePair
条目列表的输入字符串。输入字符串的格式为
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]));
var orr=from pco in(overrides??string.Empty).Split(新字符[]{';},StringSplitOptions.RemoveEmptyEntries)
让pair=pco.Split(新字符[]{':'},StringSplitOptions.RemoveEmptyEntries)
选择新的KeyValuePair(对[0],float.Parse(对[1]);
现在,如果输入字符串的格式不正确,linq将在两个可能的点上失败:在pair[]
上索引超出范围,在float.Parse上出现格式异常。这两个异常都会突然出现,对调用方来说毫无意义
我知道我有两种解决方法(不是像20世纪90年代那样使用linq和循环,也不是抓住上面的异常并重新打包),但是我想知道如果我检测到异常(pair.length一个简单的选项是将其改为:
// 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);
}
//我想我不会像这样使用??但这不是问题的重点。
var unparsed=(overrides??string.Empty).Split(新字符[]{';'},
StringSplitOptions.RemoveEmptyEntries);
var parsed=unparsed.Select(x=>ParsePair(x));
...
静态KeyValuePair ParsePair(字符串文本)
{
//注意,使用IndexOf/Substring可能会更有效
string[]bits=text.Split(新字符[]{':'},StringSplitOptions.RemoveEmptyEntries);
如果(位长度!=2)
{
抛出新ArgumentException(“值应为冒号分隔的键/浮点对”);
}
浮动值;
if(!float.TryParse(位[1],输出值))
{
抛出新ArgumentException(“无法将“+位[1]+”解析为浮点”);
}
返回新的KeyValuePair(位[0],值);
}
对于“序列”部分,您仍然使用LINQ——您只是将“如何处理单个值”部分分解为一个单独的方法(您可以将其作为一个大语句lambda来执行,但我不会)。请注意,通过这样做,您可以独立地测试ParsePair
方法
(您可能只需要。选择(ParsePair)
,这取决于您使用的是哪个版本的C。不过,方法组转换和类型推断并不是最好的朋友。)一个简单的选择是将其改为:
// 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);
}
//我想我不会像这样使用??但这不是问题的重点。
var unparsed=(overrides??string.Empty).Split(新字符[]{';'},
StringSplitOptions.RemoveEmptyEntries);
var parsed=unparsed.Select(x=>ParsePair(x));
...
静态KeyValuePair ParsePair(字符串文本)
{
//注意,使用IndexOf/Substring可能会更有效
string[]bits=text.Split(新字符[]{':'},StringSplitOptions.RemoveEmptyEntries);
如果(位长度!=2)
{
抛出新ArgumentException(“值应为冒号分隔的键/浮点对”);
}
浮动值;
if(!float.TryParse(位[1],输出值))
{
抛出新ArgumentException(“无法将“+位[1]+”解析为浮点”);
}
返回新的KeyValuePair(位[0],值);
}
对于“序列”部分,您仍然使用LINQ——您只是将“如何处理单个值”部分分解为一个单独的方法(您可以将其作为一个大语句lambda来执行,但我不会)。请注意,通过这样做,您可以独立地测试ParsePair
方法
(您可能只需要。选择(ParsePair)
,这取决于您使用的是哪个版本的C。不过,方法组转换和类型推断并不是最好的朋友。)您可以先用正则表达式测试字符串
Regex r = new Regex(@"^((\w:\d);)*$");
bool test = r.IsMatch(tosplit);
可以先用正则表达式测试字符串
Regex r = new Regex(@"^((\w:\d);)*$");
bool test = r.IsMatch(tosplit);
我想我想做的是不可能的,因为作为语句的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]));
var pairIsValidOrDie=new Func(对=>{
浮动金额;
if(pair.Length!=2 | | |!float.TryParse(pair[1],out amt))抛出新的ArgumentException(“错误:无效的价格覆盖字符串”);
返回true;
});
var orr=来自pco in(overrides??string.Empty).Split(新字符[]{';'},StringSplitOptions.RemoveEmptyEntries)
让pair=pco.Split(新字符[]{':'},StringSplitOptions.RemoveEmptyEntries)
其中pairIsValidOrDie(对)
选择新的KeyValuePair(对[0],float.Parse(对[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]));
var pairIsValidOrDie=new Func(对=>{
浮动金额;
if(pair.Length!=2 | | |!float.TryParse(pair[1],out amt))抛出新的ArgumentException(“错误:无效的价格覆盖字符串”);
返回true;
});
var orr=来自pco in(overrides??string.Empty).Split(新字符[]{';'},StringSplitOptions.RemoveEmptyEntries)
让pair=pco.Split(新字符[]{':'},StringSplitOptions.RemoveEmptyEntries)
其中pairIsValidOrDie(对)
选择新的KeyValuePair(对[0],float.Parse(对[1]);
< /代码>配对。长度不会有任何问题。可以使用WHERE子句。对于浮点。解析可以尝试用TyPARSE进行构造,但在这种情况下,应该考虑将LINQ分解为LINQ+FURACH部分,以便可读性;)@ J.Stun,正确,抱歉,纠正。不用担心,只是不希望人们关注拼写错误。=)(就像我做的一样!);)您是否只想在第一个问题上抛出一个异常