【问题标题】:Using variables in the lambda在 lambda 中使用变量
【发布时间】:2013-08-14 01:18:34
【问题描述】:

我正在使用 Linq 过滤一些东西,有时我需要使用反射来获取值。示例如下:

//...
PropertyType[] properties = myType.GetProperties();
var filtered = properties.Where(p=>p.PropertyType==typeof(MyMetaData) 
&& ((MyType)p.GetValue(obj)).Name=="name"
&& ((MyType)p.GetValue(obj)).Length==10
).ToList();
//...

在我的示例中,我不止一次使用 GetValue() 方法。如果我可以使用变量来存储它,有没有办法?我认为这将有助于提高性能。

【问题讨论】:

    标签: c# linq filtering


    【解决方案1】:

    看起来在LINQ 中包含一些variable,我们必须使用expression query,而不是method query,如下所示:

    var filtered = (from x in properties
                   let a = (x.PropertyType is MyType) ? (MyType) x.GetValue(obj) : null
                   where a != null && a.Name == "name" && a.Length == 10).ToList();
    

    我认为这也适用于 method query 和一些 Select

    var filtered = properties.Select(p=> new {p, a = (p.PropertyType is MyType) ? (MyType) p.GetValue(obj) : null})
                             .Where(x=>x.a != null && x.a.Name == "name" && x.a.Length == 10)
                             .Select(x=>x.p).ToList();
    

    【讨论】:

    • 可以在 lambda 语法中做同样的事情。实际上,let 语法等同于Select(x => new { a, x})。它只是更冗长。
    • @SimonBelanger 在阅读您的评论之前,我已经在method style 中进行了编辑,谢谢。
    • @KingKing 我在运行您提供的查询时遇到了一些问题。它在按 MyMetadata 类型过滤属性之前转换为 MyType。它失败了,因为有一些其他属性无法转换为 MyType。
    • @KingKing 感谢您的帮助!我很感激。
    【解决方案2】:

    下面的内容应该适用于method expression(lambda 语法)

        var filtered = properties.Where(p => 
            {
                if(!p.PropertyType is MyMetaData)
                {
                    return false;
                }
                var item = (MyType) p.GetValue(obj);
                return item.Name == "name"
                    && item.Length == 10
            }
        ).ToList();
    

    【讨论】:

    • 我修改了你的代码并且可以工作。我不确定它是否有效。
    • @Dilshod,您可以在最后一个子句中添加条件,如return !p.PropertyType is MyMetaData && item.Name == "name" && ...,它与上述相同,但IMO更具可读性。
    • 以前就是这样,但它在过滤属性之前尝试进行类型转换。有些属性不能转换为 MyType。这就是为什么我在转换之前尝试查看类型是否为 MyMetaData。
    • @Dilshod,因为您使用的是&&,这将导致短路,如果第一个条件解析为 false,它将不会进一步移动。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-11
    • 2010-10-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多