Linq. Select

S

shapper

Hello,

I have the following code:

article.TagsCsv = String.Join(", ", article.Tags.Select(t =>
t.Name).ToArray());

If picks all the tags on an article, joins them, and place the CSV
result in the property TagsCsv.

I am trying to do the same but for many articles:

articles.Select(a => a.TagsCsv = String.Join(", ", a.Tags.Select
(t => t.Name).ToArray()));

This is not working.

What am I doing wrong?

Thanks,
Miguel
 
P

Pavel Minaev

Hello,

I have the following code:

      article.TagsCsv = String.Join(", ", article.Tags.Select(t =>
t.Name).ToArray());

If picks all the tags on an article, joins them, and place the CSV
result in the property TagsCsv.

I am trying to do the same but for many articles:

      articles.Select(a => a.TagsCsv = String.Join(", ", a.Tags..Select
(t => t.Name).ToArray()));

This is not working.

What exactly are you trying to do, and what exactly do you mean by
"not working"? All I see here is abuse of Select() where a plain
foreach would do:

foreach (var a in articles) { a.TagsCsv = ... }

Select() is _not_ a general purpose replacement for foreach. It's
supposed to be used for projection operations, not to perform some
action for all elements of the sequence.

Or are you trying to build a _single_ CSV string from tags of several
acticles? In this case, use SelectMany:

String.Join(", ", articles.SelectMany(a => a.Tags.Select(t =>
t.Name)).ToArray())
 
S

shapper

What exactly are you trying to do, and what exactly do you mean by
"not working"? All I see here is abuse of Select() where a plain
foreach would do:

  foreach (var a in articles) { a.TagsCsv = ... }

Select() is _not_ a general purpose replacement for foreach. It's
supposed to be used for projection operations, not to perform some
action for all elements of the sequence.

Or are you trying to build a _single_ CSV string from tags of several
acticles? In this case, use SelectMany:

  String.Join(", ", articles.SelectMany(a => a.Tags.Select(t =>
t.Name)).ToArray())

No,

I am only trying to fill the property TagsCsv in each Article from its
Tags property.
I now I could use a for loop but I would also like to know how to make
this using Linq. Isn't it possible?

When I say that is not working is that after I apply my code line
TagsCsv keeps being null.

Thanks,
Miguel
 
P

Pavel Minaev

I am only trying to fill the property TagsCsv in each Article from its
Tags property.
I now I could use a for loop but I would also like to know how to make
this using Linq. Isn't it possible?

It is possible, but highly not desirable. LINQ and expressions with
side effects (this includes all kinds of statements) do not mix well.
To reiterate: if you need to _perform some action_ on each element of
a collection, you should use foreach - that's what it is designed for
(and what LINQ is _not_ designed for). If you need to project, filter,
order, or otherwise process a sequence, getting a _new_ sequence as a
result of the operation, only then you should use LINQ.
When I say that is not working is that after I apply my code line
TagsCsv keeps being null.

From MSDN documentation for Enumerable.Select (and most other methods
of class Enumerable):

"This method is implemented by using deferred execution. The immediate
return value is an object that stores all the information that is
required to perform the action. The query represented by this method
is not executed until the object is enumerated either by calling its
GetEnumerator method directly or by using foreach in Visual C# or For
Each in Visual Basic."

What happens here is that when you call select, it just remembers the
collection on which Select was called, and the lambda that you passed.
It does not do anything until you start enumerating the result;l and
if you never enumerate it - such as your case here, where you just
throw it away - it's not going to do anything. Even if you start
enumerating it, it will try to be as lazy as possible (i.e. it will
only call the lambda for those elements of the collection that you
enumerate, and not for all of it).

If you call ToArray() on the return value of Select(), then you'll see
your lambda actully execute for all elements.

And this is precisely what I mean when I say that LINQ is not designed
for such tasks (side-effects). Always use side-effect free lambdas
with LINQ, always. If you do, you won't fall into traps like this one,
and you'll be able to switch to PLINQ (or some other optimized LINQ
provider) easily if needed.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Similar Threads

List 2
Linq. Please, need help. 1
(Collection) 1
Filter 1
Condition 2
ToString and FromString 10
Select in Linq. Could someone, please, check it out? 3
Linq. Select 1

Top