是否有一种优雅的方式来构建IEnumerable<T>
来自
bool TryParse<T>(Input, out T)
和
类型的输入Input[,]
基本上我有一个输入的2D数组,想在每个输入上调用TryParse,如果TryParse<T>
返回true,我会将返回值附加到&#39; out&#39;到IEnumerable<T>
。
我可以在for循环中轻松完成这项工作,但我想要更优雅的东西。这就是我现在使用的:
var marketInputColl = new Collection<MarketInput>();
foreach (object o in marketInputs)
{
MarketInput mktInput;
if (ExcelCache.TryGetCache<MarketInput>(o.ToString(), out mktInput))
marketInputColl.Add(mktInput);
}
答案 0 :(得分:2)
out / ref参数并不能很好地发挥作用。你可以做到,但它很乱。最好的选择是使用一个解析工具,它将返回一个可以为null的int(如果无法解析该值,则返回null),而不是使用out
:
public static int? TryParse(string s)
{
int output;
if (int.TryParse(s, out output))
return output;
else
return null;
}
只要您不需要存储实际的 null
值,您就可以为尝试从缓存中获取值创建类似的功能。
这允许你写:
var query = data.Select(item => TryGetCache(item.ToString()))
.Where(n => n != null);
答案 1 :(得分:2)
您可以通用方式执行此操作:
static class Extensions
{
public delegate bool TryParseDelegate<TSource>(string s, out TSource source);
public static IEnumerable<TResult> WhereParsed<TSource, TResult>(
this IEnumerable<TSource> source,
TryParseDelegate<TResult> tryParse)
{
// check arguments against null first
foreach (var item in source)
{
TResult result;
if (tryParse(item.ToString(), out result))
{
yield return result;
}
}
}
}
用法:
var result = marketInputs.Cast<object>()
.WhereParsed<object, MarketInput>
// need to specify explicit,
// out param type cannot be inferred from usage
(ExcelCache.TryGetCache).ToList();
答案 2 :(得分:1)
TryParse()
的问题在于它不是任何接口的实现:您需要使用反射来查找方法,或者(更简单),只需提供转换委托
然后你可以用2D数组做这样的事情(或者实际上是任意数量的数组:
string[,] raw = { { "1" , "2" , } ,
{ "3" , "X" , } ,
{ "5" , "6" , } ,
} ;
int?[] converted = raw.Cast<string>()
.Select( s => {
int value ;
bool parsed = int.TryParse( s , out value ) ;
return parsed ? (int?) value : (int?)null ;
})
.ToArray()
;
如果你的阵列是锯齿状的,你还需要再做一步:
string[][] raw = { new string[]{"1","2",} ,
new string[]{"3","X",} ,
new string[]{"5","6",} ,
} ;
int?[] converted = raw.Cast<string[]>()
.SelectMany( s => s )
.Select( s => {
int value ;
bool parsed = int.TryParse( s , out value ) ;
return parsed ? (int?) value : (int?)null ;
})
.ToArray()
;
鉴于你的例子:
var marketInputColl = new Collection<MarketInput>();
foreach (object o in marketInputs)
{
MarketInput mktInput;
if (ExcelCache.TryGetCache<MarketInput>(o.ToString(), out mktInput))
marketInputColl.Add(mktInput);
}
我们可以采用相同的基本方法:
Collection<MarketInput> collection = new Collection<MarketInput>(
marketInputs
.Cast<object>()
.Select( o => o.ToString() )
.Select( s => {
MarketInput v ;
bool parsed = ExcelCache.TryGetCache<MarketInput>( s , out v ) ;
return parsed ? v : null ;
})
.Where( x => x != null )
.ToList()
) ;