【问题标题】:C# lambda: Why isn't this line of code working?C# lambda:为什么这行代码不起作用?
【发布时间】:2017-07-03 20:49:31
【问题描述】:

这行不行:

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

错误 CS0201 只有赋值、调用、递增、递减和新对象表达式可以作为语句使用

【问题讨论】:

  • elements.ForEach(x => x.GetType() == type) 不返回一个列表,你的意思是在哪里?
  • AddRange 不返回值。你的意思是elements.Where(x =&gt; x.GetType() == type).ToList()
  • 使用List&lt;T&gt;(IEnumerable&lt;T&gt;) constructor instead of the parameterless constructor. Or use a LINQ query followed by a ToList()`
  • @Emily,看看this 解决方案是否适合你...

标签: c# lambda


【解决方案1】:

因为List.AddRange返回void,而void不能作为返回值。

这应该可以解决问题:

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

或者:

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

如果您可以将type 表达为实际类型,例如string,您甚至可以使用这个:

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

【讨论】:

  • 这个答案中的解决方案是完全正确的,但是提到的错误(错误 CS0201)是由内部 ForEach 及其 lambda 表达式引起的,而不是由 AddRange 方法引起的。
  • 好的,可能两者都有,因为两者都会给出例外,但感谢您指出@lukegv
【解决方案2】:

我了解到您希望按类型过滤通用列表。
您提供的代码 sn-p 不起作用,原因有以下三个:

  1. .AddRange(...) 不返回列表,而是返回void,因此它不能用于流畅的语法。如果 lambda 声明允许 var,您可以通过
    ... => { var lst = new List<T>(); lst.AddRange(elements.Where(x => x.GetType() == type)); return lst; } 解决此问题,但不幸的是他们不允许这样做。所以你需要添加另一个参数来传递List&lt;T&gt;
  2. sn-p 使用泛型的方式存在问题:您不能只声明 List&lt;T&gt; 而不提供泛型参数 T,无论是在类级别还是在函数级别。
  3. .ForEach(...) 不是这里的正确方法,您需要一个 .Where(...) 方法。

考虑到上面的题目,你可以这样解决(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}");
    }
}

它从elements 列表中过滤字符串并返回它们,即输出为:

你好
世界

扩展方法的好处是您只需要指定 2 个参数之一(如 Main 方法中所示)。您也可以将其与 2 个参数一起使用,或者您也可以将其声明为普通函数 - 但在这里我认为使用它有一个优势。

Try it with .NET Fiddle

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-11-05
    • 1970-01-01
    • 2011-07-24
    • 2017-05-24
    • 1970-01-01
    • 1970-01-01
    • 2010-09-18
    相关资源
    最近更新 更多