Eldar
Eldar

Reputation: 153

C# lambda: Why isn't this line of code working?

This line won't work:

public List<T> GetTypes(Type type) => new List<T>().AddRange(
                                        elements.ForEach(x => x.GetType() == type)
                                      );

Error CS0201 Only assignment, call, increment, decrement, and new object expressions can be used as a statement

Upvotes: 0

Views: 633

Answers (2)

Matt
Matt

Reputation: 27001

I understand that you want to filter a generic list by type.
The code snippet you provided does not work, because of three reasons:

  1. .AddRange(...) does not return a list but void, hence it cannot be used in fluent syntax. You could fix that via
    ... => { var lst = new List<T>(); lst.AddRange(elements.Where(x => x.GetType() == type)); return lst; } if lambda declarations would allow var, but unfortunately they don't allow it. So you need to add another parameter passing a List<T>.
  2. There is an issue with the way the snippet is using generics: You can't just declare a List<T> without providing a generic parameter T, either on class level, or on function level.
  3. .ForEach(...) is not the right method here, you need a .Where(...) method.

Taking into account the topics above, you can solve it as follows (static is required because extension methods must be static):

using System;
using System.Collections.Generic;
using System.Linq;

public static class Extensions
{
    // Extension method: filters elements by type
    public static List<T> GetTypes<T>(this List<T> elements, Type type)
                => elements.Where(x => x.GetType() == type).ToList();
}

public class Program
{
    // demonstrates how it is working
    public static void Main()
    {
        var elements = new List<object> {
            (int)3, (string)"Hello", (int)5, (string)"World"
        };
        var filteredList = elements.GetTypes(typeof(System.String));
        foreach (var x in filteredList) Console.WriteLine($"{x}");
    }
}

It filters the strings from the elements list and returns them, i.e. the output is:

Hello
World

Extension methods have the benefit that you only need to specify one of the 2 parameters (as demonstrated in the Main method). You can also use it with 2 parameters, or you could declare it as a normal function as well - but here I think there is an advantage to use it.

Try it with .NET Fiddle

Upvotes: 1

Patrick Hofman
Patrick Hofman

Reputation: 156938

Because List.AddRange returns void, and voids can't be used as return values.

This should do the trick though:

new List<T>(elements.Where(x => x.GetType() == type))

Or:

elements.Where(x => x.GetType() == type).ToList()

And if you can express type as the actual type, like string, you could even use this:

elements.OfType<string>().ToList()

Upvotes: 4

Related Questions