tags:

views:

165

answers:

5

consider this:

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

now why test is empty after that ? i dont care about the return of that actually i know its IEnumerable.

any way if this is all seems a mess then how can i convert IEnumerable<char> to string ?

thanks in advance..

+8  A: 

Because you didn't execute the query. Linq is lazy. It will be executed when you do either foreach or ToList/ToArray/ToDictionary.

and i advice to do it like that

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

or even using

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

More on that. Select is intended to apply some kind of transformation to every element in sequence. This operation is also known as map. If you want to produce single element from sequence it is Aggregate, aka reduce. It is not lazy, it forces execution of query.

Andrey
`Remove`? I think you mean `Substring`?
Timwi
Silly programmers thinking their statements will be executed. Pashaw!
Greg
@Greg Linq is declarative framework. this is sometimes surprising stuff for imperative-minded developers.
Andrey
This will not compile if `somestring` is of type `IEnumberable<string>`. The string class does not have an overloaded constructor that takes a string array.
0xA3
@0xA3 you are right and wrong. It will compile, because i pass `char[]` not `string[]`. in second case it won't compile
Andrey
@0xA3 somestring is `string`, thus `IEnumerable<char>`
Andrey
Yes, you are right, of course. When I wrote my comment, the question asked about `IEnumerable<string>`, hence I assumed `somestring` is of that type.
0xA3
@Andrey: Yep, downright confusing I'd say. "Sometimes when you do things with LINQ, they don't do anything at all".
Greg
+2  A: 

Because Select is lazy, so the function you pass in will only be evaluated once you use the result of Select.

Generally it's bad idea to use functions with side effects with Select. You should probably use foreach instead.

In this particular case, you can just use the String.Join method.

sepp2k
+2  A: 

Select returns an IEnumerable<char> but you aren't enumerating it in your code so the delegate won't be executed. If you change it to:

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

Because you only declared the sequence, but you never executed it. If you added another .ToList() at the end, then test would have the characters in it.

However, I strongly recommend against this practice. You are using the evaluation of a sequence to cause side-effects. You have already discovered that the results are confusing. If you really just want the first 50 items of a sequence, just use Take alone:

var partSequence = fullSequence.Take(50);

Your above example could be written something like this:

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

but I’m sure you’re aware of string.Substring() for this purpose.

Timwi
+6  A: 

(Others have explained why it doesn't work.)

Your question doesn't quite make sense at the moment - it's not clear whether you're actually dealing with an IEnumerable<char> or an IEnumerable<string>. (Your text suggests IEnumerable<string>; your code suggests IEnumerable<char>). If it's an IEnumerable<string> and you're using .NET 4, it's really easy:

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

If you're using .NET 3.5, it's still pretty easy:

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

Obviously use something like "," if you want a delimiter between the strings.

If you're dealing with a general IEnumerable<char> then use

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

If you're actually dealing with a string to start with, use Substring :)

Jon Skeet
Yeah, but I think he’s wondering why his code didn’t work.
Timwi
he iterates over string, see `delegate(char x)`. I don't think that it is efficient to do string.Join over ienumerable of chars.
Andrey
@Andrey: I was basing the answer on the claim that he's trying to concatenate an `IEnumerable<string>`, not an `IEnumerable<char>`... basically the question's broken at the moment. I've edited to indicate that.
Jon Skeet
yeah i meant ienumrable<char> not string that was a typo sorry
Stacker
"" over string.Empty? Go iron your hands :P
annakata
@Stacker: Okay, that changes things - use the bottom approach (which Timwi had also suggested).
Jon Skeet
@annakata: I've explained elsewhere why I prefer "" over `string.Empty` - I find it more readable.
Jon Skeet