1

In the code below, I'm adding a parameterValue for each row in the parameters datatable.

However, I'm getting the following error:

"The type arguments for method 'EnumerableRowCollectionExtensions.Select(EnumerableRowCollection, Func)' cannot be inferred from the usage. Try specifying the type arguments explicitly."

Can someone help me understand what type argument I need to explicitly define in the code?

Here is the code with the error:

parameters.AsEnumerable().Select(x => 
{
    ParameterValue parameterValue = new ParameterValue();
    parameterValue.Name = x["name"].ToString();
    parameterValue.Value = x["value"].ToString();
    parameterList.Add(parameterValue);
 });

This works fine in a foreach loop. Here is the code for that:

foreach (DataRow row in parameters.Rows)
{
   ParameterValue parameterValue = new ParameterValue();
   parameterValue.Name = row["name"].ToString();
   parameterValue.Value = row["value"].ToString();

   parameterList.Add(parameterValue);
}
rds80
  • 631
  • 1
  • 10
  • 23
  • 1
    `Select` expects a function that returns the desired object. It's not a synonym for `ForEach` or `Apply`. In fact, it shouldn't have side-effects – Panagiotis Kanavos Nov 08 '17 at 15:01
  • https://meta.stackoverflow.com/questions/284236/why-is-can-someone-help-me-not-an-actual-question – Raedwald Nov 08 '17 at 15:22

2 Answers2

3

The correct syntax of

parameters.AsEnumerable().Select(x => 
{
    ParameterValue parameterValue = new ParameterValue();
    parameterValue.Name = x["name"].ToString();
    parameterValue.Value = x["value"].ToString();
    parameterList.Add(parameterValue);
 });

is

parameterList.AddRange(parameters.AsEnumerable().Select(x =>            
    new ParameterValue()
    {
        Name = x["name"].ToString(),
        Value = x["value"].ToString()
    }));

Side note: instead of x["name"].ToString() you should access the field by its type x.Field<string>("name")

fubo
  • 44,811
  • 17
  • 103
  • 137
  • Depends on what `parameterList` is, maybe it doesn't have an `AddRange` method. I'd store the query in a variable and either use a `foreach` to add them one after another or use `AddRange(allParameterValues)` if supported. – Tim Schmelter Nov 08 '17 at 15:03
  • @TimSchmelter: my apologies. parameterList is: List parameterList = new List(); – rds80 Nov 08 '17 at 15:10
  • @fubo is using Field a better practice because of type safety? – rds80 Nov 08 '17 at 15:43
  • @rds80 you don't need any kind of convertion like `Convert.ToInt32(x["foo"])` and it's best practice https://stackoverflow.com/a/7104767/1315444 – fubo Nov 08 '17 at 15:55
1

Enumerable.Select is a projection method. It projects each input item of type TSource into the new form of type TResult. Thus it accepts a selector delegate which does this TSource > TResult projection. Your selector delegate looks like this:

x => 
{
    ParameterValue parameterValue = new ParameterValue();
    parameterValue.Name = x["name"].ToString();
    parameterValue.Value = x["value"].ToString();
    parameterList.Add(parameterValue);
}

I.e. it takes DataRow as TSource and projects it to.. nothing. You do not return any value from this delegate. Thus compiler cannot understand which TResult it should use.

Now solution. Actually, you want to do two actions here:

  • project each row to ParameterValue
  • add each projected value to the list (new or existing)

First part is projection. Just use delegate which takes a DataRow as TSource and returns ParameterValue as TResult:

x => new ParameterValue{ Name = x.Field<string>("name"), Value = x.Field<string>("value") }

The second part can be done in two ways. You can create a new list from all parameter values. This is a declarative style of programming - instead of specifying how to add values to list you just say 'I want list':

var parameterList = parameters.AsEnumerable()
      .Select(r => new ParameterValue { 
          Name = r.Field<string>("name"), // note this LINQ to DataSet syntax
          Value = r.Field<string>("value")
      }).ToList();

Or you can use a simple foreach loop to add each projected value one by one to existing list. But here I would use query syntax for projection:

var parameterValues = from r in parameters.AsEnumerable()
                      select new ParameterValue { 
                          Name = r.Field<string>("name"),
                          Value = r.Field<string>("value")
                      };

foreach(var parameterValue in parameterValues)
    parameterList.Add(parameterValue);
Sergey Berezovskiy
  • 232,247
  • 41
  • 429
  • 459