1

任意の文字列を厳密に型指定されたリストに分割できるようにする Split 拡張機能を作成したいと考えています。私は有利なスタートを切りましたが、これを多くのプロジェクトで再利用するつもりだったので、コミュニティから意見を求めたいと思います (それで、自分のツールボックスに追加できます ;) ここから何かアイデアはありますか?

public static class Converters
{
    public static IEnumerable<T> Split<T>(this string source, char delimiter)
    {
        var type = typeof(T);

        //SPLIT TO INTEGER LIST
        if (type == typeof(int))
        {
            return source.Split(delimiter).Select(n => int.Parse(n)) as IEnumerable<T>;
        }

        //SPLIT TO FLOAT LIST
        if (type == typeof(float))
        {
            return source.Split(delimiter).Select(n => float.Parse(n)) as IEnumerable<T>;
        }

        //SPLIT TO DOUBLE LIST
        if (type == typeof(double))
        {
            return source.Split(delimiter).Select(n => double.Parse(n)) as IEnumerable<T>;
        }

        //SPLIT TO DECIMAL LIST
        if (type == typeof(decimal))
        {
            return source.Split(delimiter).Select(n => decimal.Parse(n)) as IEnumerable<T>;
        }

        //SPLIT TO DATE LIST
        if (type == typeof(DateTime))
        {
            return source.Split(delimiter).Select(n => DateTime.Parse(n)) as IEnumerable<T>;
        }

        //USE DEFAULT SPLIT IF NO SPECIAL CASE DEFINED
        return source.Split(delimiter) as IEnumerable<T>;
    }
}
4

4 に答える 4

9

変換関数のパラメーターを追加します。

public static IEnumerable<T> Split<T>(this string source, Func<string, T> converter, params char[] delimiters)
{
    return source.Split(delimiters).Select(converter);
}

そして、あなたはそれを次のように呼び出すことができます

IEnumerable<int> ints = "1,2,3".Split<int>(int.Parse, ',');

また、インスタンス メソッドとの混同を避けるために名前を変更することも検討しString.Splitます。これは、オーバーロードの解決が複雑になり、他のメソッドとは異なる動作をするためです。

編集:変換関数を指定したくない場合は、型コンバーターを使用できます。

public static IEnumerable<T> SplitConvert<T>(this string str, params char[] delimiters)
{
    var converter = TypeDescriptor.GetConverter(typeof(T));
    if (converter.CanConvertFrom(typeof(string)))
    {
        return str.Split(delimiters).Select(s => (T)converter.ConvertFromString(s));
    }
    else throw new InvalidOperationException("Cannot convert type");
}

これにより、事前定義されたリストに依存するのではなく、変換を他の型に拡張できます。

于 2012-06-02T11:15:01.240 に答える
5

Lee の提案には同意しますが、個人的には、標準の LINQ 操作で簡単に実現できるものに対して新しい拡張メソッドを定義する価値はないと思います。

IEnumerable<int> ints = "1,2,3".Split(',').Select(int.Parse);
于 2012-06-02T11:41:18.623 に答える
2
public static IEnumerable<T> Split<T>
      (this string source, char delimiter,Converter<string,T> func)
{
     return source.Split(delimiter).Select(n => func(n)));
}

例:

"...".Split<int>(',',p=>int.Parse(p))

または、define関数なしでConverter.ChangeTypeを使用できます。

public static IEnumerable<T> Split<T>(this string source, char delimiter)
{
     return source.Split(delimiter).Select(n => (T)Convert.ChangeType(n, typeof(T)));
}
于 2012-06-02T11:23:27.843 に答える
1

私はこの方法が好きではありません。文字列からのデータ型の解析(一種の逆シリアル化)は、より複雑なデータ型を処理する場合、非常に型とコンテンツに敏感なプロセスですint。たとえば、現在のカルチャを使用DateTime.Parseして日付を解析するため、このメソッドでは、システム間で日付の一貫性のある、または信頼性の高い出力が提供されません。また、すべてのコストで日付を解析しようとするため、状況によっては不適切な入力と見なされる可能性のあるものをスキップする可能性があります。

文字列を厳密に型指定されたリストに分割するという目標は、ハードコードされた変換を使用する単一の方法では実際には達成できません。特に、目標が幅広いユーザビリティである場合はそうです。新しい変換で繰り返し更新しても。それを実行するための最良の方法は、"1,2,3".Split(",").Select(x => whatever)ダグラスが上で提案したようにすることです。また、どのような変換が行われているのかも非常に明確です。

于 2012-06-02T12:19:04.023 に答える