Ulhas Tuscano
Ulhas Tuscano

Reputation: 5620

Whats wrong with my lambda expression

I want to get string of checkedListbox selected values like 1,3,4. To achieve this i have written a lambda expression:

private string GetCheckedIDs(CheckBoxList chkLst)
{
    string chkedVal = string.Empty;
    ((List<string>)chkLst.Items.OfType<ListItem>().Where(s => s.Selected).Select(s => s.Value))
                                                                         .ForEach(item => chkedVal = item + ",");
   return chkedVal.Remove(chkedVal.LastIndexOf(","));
}

The error I am getting is:

Unable to cast object of type
'WhereSelectEnumerableIterator`2[System.Web.UI.WebControls.ListItem,System.String]' to type 'System.Collections.Generic.List`1[System.String]'.

Upvotes: 2

Views: 1247

Answers (2)

Kobi
Kobi

Reputation: 138137

Nothing is wrong with your lambda expression - the problem is the casting from IEnumerable<String> to List<String> You can't cast to a list, but this should work:

chkLst.Items.OfType<ListItem>()
      .Where(s => s.Selected)
      .Select(s => s.Value).ToList()
      .ForEach(item =>   chkedVal = item + ",");

Here is a better option, using String.Join(String, IEnumerable<String>). It still selects the strings, but avoids string concatenation (and the last comma!):

string chkedVal = String.Join(",", chkLst.Items.OfType<ListItem>()
                                    .Where(s => s.Selected).Select(s => s.Value))

Or on .Net 3.5 you don't have that handy overload - you need to create an array for String.Join(String, String[]):

string chkedVal = String.Join(",", chkLst.Items.OfType<ListItem>()
                                     .Where(s => s.Selected)
                                     .Select(s => s.Value).ToArray())

Upvotes: 4

Merlyn Morgan-Graham
Merlyn Morgan-Graham

Reputation: 59151

The code may compile, but you'll get that error at run time. This is because the IEnumerable<string> returned by Linq isn't actually a list. This is for performance reasons, otherwise Linq would have to build the whole list up front, instead of building each item as it is needed.

There is a Linq method on IEnumerable<T> to force Linq to build the list up front, though - ToList:

chkLst.Items
    .OfType<ListItem>()
    .Where(s => s.Selected)
    .Select(s => s.Value)
    .ToList()
    .ForEach(item => chkedVal = item + ",");

Upvotes: 1

Related Questions