読者です 読者をやめる 読者になる 読者になる

List を文字列化

C#

List<Char>.ToString() とか

C# 3.0 以降なら LINQ やら拡張メソッドやらで OK ですね。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication
{
    class Program
    {
        static void Main(string[] args)
        {
            var hello = "hello";
            // 元ネタにあわせるためにToListを呼び出す
            var buf = hello.ToCharArray().ToList();
            // LINQ
            Console.WriteLine(buf.Aggregate("", (s, c) => s + c));

            // 拡張メソッド
            Console.WriteLine("".ToCharArray().Join(","));
            Console.WriteLine("h".ToCharArray().Join(","));
            Console.WriteLine("hello".ToCharArray().Join(","));
        }
    }

    public static class IEnumerableExtension
    {
        // out引数が使えないので仕方がないからStringBuilderで
        static IEnumerable<T> SkipFirst<T>(this IEnumerable<T> self, StringBuilder skipped)
        {
            using (var itr = self.GetEnumerator())
            {
                if (itr.MoveNext() == false)
                    yield break;
                skipped.Append(itr.Current);

                while (itr.MoveNext())
                {
                    yield return itr.Current;
                }
            }
        }

        public static string Join<T>(this IEnumerable<T> self, string separator)
        {
            var skipped = new StringBuilder();
            return self.SkipFirst(skipped).Aggregate(skipped, (res, c) => res.Append(separator).Append(c)).ToString();
        }
    }
}

メソッドチェインの方はさすがに直感的とはいえないけどねー


追記:
ぶくまで指摘があったように、string は IEnumerable を実装してるので、ToCharArray() の呼び出しは要らないです。
なんで、Main メソッドの中身は実はこう書ける。

var hello = "hello";
// 元ネタにあわせるためにToListを呼び出す
var buf = hello.ToList();
// LINQ
Console.WriteLine(buf.Aggregate("", (s, c) => s + c));

// 拡張メソッド
Console.WriteLine("".Join(","));
Console.WriteLine("h".Join(","));
Console.WriteLine("hello".Join(","));

インテリセンスに出てこないから string は古い方の IEnumerable しか実装してないんだと思ってた・・・
ありがとうございます! > id:neuecc


で・・・

[SerializableAttribute] 
[ComVisibleAttribute(true)] 
public sealed class String : IComparable, ICloneable, IConvertible, 
    IComparable<string>, IEnumerable<string>, IEnumerable, 
    IEquatable<string>
String クラス(.NET Framework 2.0)
[SerializableAttribute] 
[ComVisibleAttribute(true)] 
public sealed class String : IComparable, ICloneable, IConvertible, 
    IComparable<string>, IEnumerable<string>, IEnumerable, 
    IEquatable<string>
String クラス (.NET Framework 3.0)

あれ? IEnumerable
3.5 の方はというと、

[SerializableAttribute]
[ComVisibleAttribute(true)]
public sealed class String : IComparable, 
    ICloneable, IConvertible, IComparable<string>, IEnumerable<char>, 
    IEnumerable, IEquatable<string>
String クラス (.NET Framework 3.5)

おー、直ってる。