Harry Boy Harry Boy - 1 month ago 5
C# Question

Set several class values using LINQ expression

I have the following two LINQ statements which set different values in the same item in a list

List<MyClass> myList = GetList();

myList.Where(x => x.Name == "someName").Select(x => x.MyArray = someList.ToArray()).ToList();
myList.Where(x => x.Name == "someName").Select( x => x.AnotherValue = GetValue()).ToList();


Is it possible to combine this so both are set in the one expression?

Answer
myList
    .Where(x => x.Name == "someName")
    .ToList()
    .ForEach(x => {
        x.MyArray = someList.ToArray();
        x.AnotherValue = GetValue();
    });

Why are you calling ToList() at the end of each of those expressions and discarding the result?

Also, Jon Skeet is right that this is an abuse of LINQ, and especially so in your original form: It's explicit that LINQ expressions aren't even necessarily expected to be fully enumerated. The fact that you needed those ToList() calls to make anything happen should have given you a grave and queasy sense that you were misusing a language feature. When you have to do something weird to use your chosen construct instead of the usual way of doing it, finish getting it to work (because weird is cool), and then go back and redo it the boring, lame way before you check it in.

What advantage do you see in the LINQ + ForEach() version above, compared to this version?

foreach (var x in myList.Where(x => x.Name == "someName"))
{
     x.MyArray = someList.ToArray();
     x.AnotherValue = GetValue();
}

The old-style loop version is shorter, instantly understandable because it's the default idiom, and IMO cleaner. You don't have to do everything with LINQ.

N.B., ForEach() isn't LINQ; it's a member of List<T>. That's why you have to call ToList() to use it.

Comments