优雅的C#方法返回一个IEnumerable<;T>;从布尔TryParse<;T>;(Input,ou

本文关键字:gt lt 布尔 ou Input TryParse IEnumerable 方法 返回 一个 | 更新日期: 2023-09-27 18:20:10

有没有一种从构建IEnumerable<T>的优雅方法

bool TryParse<T>(Input, out T) 

和类型的输入

Input[,]

基本上,我有一个Input的2D数组,并希望在每个Input上调用TryParse,如果TryParse<T>返回true,我将把'out'中的返回值附加到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);
        }

优雅的C#方法返回一个IEnumerable<;T>;从布尔TryParse<;T>;(Input,ou

out/ref参数在LINQ中并不能很好地发挥作用。你可以做,但很乱。优选的选项是使用解析工具,该工具将返回可为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);

您可以用一种通用的方式来完成:

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

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