IEnumerable <string> to string </string>

时间:2010-09-23 11:49:30

标签: c# linq

考虑一下:

string test = "";
somestring.ToList().Take(50).Select(
    delegate(char x)
    {
        test += x;
        return x;
    }
);

现在为什么之后测试是空的?我不关心它的回归,实际上我知道它的IEnumerable。

如果这一切看起来一团糟,那我怎么能把IEnumerable<char>转换为字符串?

提前感谢..

5 个答案:

答案 0 :(得分:21)

因为您没有执行查询。 Linq很懒。当您执行foreachToList / ToArray / ToDictionary时,它会被执行。

我建议这样做

string test = new string(somestring.Take(50).ToArray());

甚至使用

string test = somestring.Substring(0, 50);

更多相关内容。 Select旨在按顺序对每个元素应用某种转换。此操作也称为map。如果您想从序列中生成单个元素,则为Aggregate,即reduce。它不是懒惰,它强制执行查询。

答案 1 :(得分:15)

(其他人解释了为什么它不起作用。)

目前你的问题没有多大意义 - 目前尚不清楚你是否实际处理IEnumerable<char>IEnumerable<string>。 (您的文字建议IEnumerable<string>;您的代码建议IEnumerable<char>)。如果它是IEnumerable<string>并且您使用的是.NET 4,那么它非常简单:

string combined = string.Join("", list.Take(50));

如果您使用的是.NET 3.5,它仍然非常简单:

string combined = string.Join("", list.Take(50).ToArray());

如果你想要字符串之间的分隔符,显然可以使用类似“,”的东西。

如果您正在与一名将军IEnumerable<char>打交道,请使用

string combined = new string(chars.Take(50).ToArray());

如果您实际上处理要开头的字符串,请使用Substring:)

答案 2 :(得分:3)

Select返回IEnumerable<char>,但您没有在代码中枚举它,因此代理将不会被执行。如果您将其更改为:

string test = "";
somestring.Take(50).Select(
    delegate(char x)
    {
        test += x;
        return x;
    }
).ToList();

答案 3 :(得分:3)

因为你只声明了序列,但你从未执行过它。如果您在结尾处添加了另一个.ToList(),那么test将包含其中的字符。

但是,我强烈建议不要这样做。您正在使用序列的评估来导致副作用。您已经发现结果令人困惑。如果你真的只想要一个序列的前50个项目,只需单独使用Take

var partSequence = fullSequence.Take(50);

上面的例子可能是这样写的:

var partString = new string(someString.Take(50).ToArray());

但我确信您已为此目的了解string.Substring()

答案 4 :(得分:2)

因为Select是惰性的,所以只有在使用Select的结果时才会评估传入的函数。

通常,选择使用带副作用的函数是个坏主意。你可能应该使用foreach。

在这种特殊情况下,您可以使用String.Join方法。