【问题标题】:How can I write a generic extension method for converting a delimited string to a list?如何编写用于将分隔字符串转换为列表的通用扩展方法?
【发布时间】:2013-03-07 01:34:38
【问题描述】:

我们经常需要将值由某个字符分隔的字符串转换为列表。我想编写一个通用扩展方法,将字符串转换为指定类型的列表。这是我目前所拥有的:

    public static List<T> ToDelimitedList<T>(this string value, string delimiter)
    {
        if (value == null)
        {
            return new List<T>();
        }

        var output = value.Split(new string[] { delimiter }, StringSplitOptions.RemoveEmptyEntries);
        return output.Select(x => (T)x).ToList();
    }

但我得到一个错误。

无法将类型“字符串”转换为类型“T”。

有没有更好的方法来做到这一点,还是我需要为不同类型的列表创建多个扩展方法并执行Convert.ToInt32() 等?

更新

我正在尝试做这样的事情:

var someStr = "123,4,56,78,100";
List<int> intList = someStr.ToDelimitedList<int>(",");

var someStr = "true;false;true;true;false";
List<bool> boolList = someStr.ToDelimitedList<bool>(";");

【问题讨论】:

  • 当涉及的唯一类型是字符串时,为什么要使用泛型方法?
  • 字符串需要转换成不同的类型。字符串中的值可以是1,2,3,4,5true,false,false,true
  • 您必须为此编写一些代码!
  • 必须返回List吗?为什么不通过 IEnumerable 获得懒惰评估

标签: c# .net linq list type-conversion


【解决方案1】:

这不是 LINQ 的完美任务吗?

您可以执行以下操作:

"1,2,3,4,5".Split(',').Select(s => Convert.ToInt32(s)).ToList();

您可以根据自己的情况更改通用 Select() 委托。

【讨论】:

    【解决方案2】:

    Convert.ChangeType 适用于原始类型和许多框架类型(假设默认解析规则足够好):

    return output.Select(x => (T) Convert.ChangeType(x, typeof(T)))
                 .ToList();
    

    如果您需要它为您自己的自定义类型工作,您必须让它们实现IConvertible 接口。

    请记住,这不够复杂,无法使用自定义转换规则,也不够强大,无法正确处理故障(除了引发异常并使整个操作失败)。如果您需要对此的支持,请提供一个接受 TypeConverter 或转换委托的重载(如 mike z 的回答)。

    【讨论】:

    • +1,哇从来不知道有Convert.ChangeType
    • 这很好用,虽然我正在考虑像 Oliver 和 p.s.w.g 所建议的那样只使用直接 linq。
    • 我接受这一点,因为它是我所问问题的答案,但正如 Ani 所说,它是善变的,可能更好地使用直接 LINQ,就像在@Oliver 的回答中一样。
    【解决方案3】:

    没有将字符串转换为任意类型T 的内置方法。您的方法必须接受某种委托:

    public static List<T> ToDelimitedList<T>(this string value, string delimiter, Func<string, T> converter)
    {
        if (value == null)
        {
            return new List<T>();
        }
    
        var output = value.Split(new string[] { delimiter }, StringSplitOptions.RemoveEmptyEntries);
        return output.Select(converter).ToList();
    }
    

    【讨论】:

      【解决方案4】:

      好像你可以只使用String.SplitEnumerable.Select

      var list = "1,2,3".Split(",").Select(s => int.Parse(s));
      

      但是如果你必须做一个扩展,试试这个...

      public static List<T> ParseDelimitedList<T>(this string value, string delimiter, Func<string, T> selector)
      {
          if (value == null)
          {
              return new List<T>();
          }
      
          var output = value.Split(new string[] { delimiter }, StringSplitOptions.RemoveEmptyEntries);
          return output.Select(selector).ToList();
      }
      
      var list = "1,2,3".ParseDelimitedList(",", s => int.Parse(s));
      

      【讨论】:

      • 这不是通用的。它只会返回int
      • 打败我! @AlexFord,它不需要是通用的,因为 Select 语句将允许您提供通用转换。
      • 不错,但也许他只是想要一个通用的解决方案?
      • @luis_laurent 这是一个通用的解决方案。不要重新发明轮子。没有理由将SplitSelect 组合成一个操作。只需独立调用这两个方法即可。
      • 啊,我明白你的意思了。根本不使用扩展程序。
      猜你喜欢
      • 2010-10-19
      • 1970-01-01
      • 2010-12-08
      • 1970-01-01
      • 1970-01-01
      • 2023-04-02
      • 1970-01-01
      • 2017-10-22
      • 1970-01-01
      相关资源
      最近更新 更多