包含在Linq to XML Where子句中的功能

问题描述

| 我在Linq to XML中的where子句的.Contains()函数中遇到意外行为。似乎在字符串函数中的功能类似于\“ == \” not Contains()。 例:
var q = from sr in SearchResults.Descendants(\"Result\")
    where _filters.Contains((string)sr.Element(\"itemtype\"))
    orderby (string)sr.Element(\"ipitemtype\") ascending
    select new SearchItem
    {
        //Create Object
        ID = (string)sr.Element(\"blabla\"),}
_filters是字符串列表。假设它包含3个值:
_filters[0] = \"videos\";
_filters[1] = \"documents\";
_filters[2] = \"cat pictures\";
现在发生的是,如果
<itemtype>videos</itemtype> 
是XML节点。 但是,如果节点是
<itemtype>videos mission critical document advertising</itemtype>,
IEnumerable返回空白,对我来说,它表示操作数的功能类似于\“ == \”而不是\“ Contains()\”。 知道我在做什么错吗? dtb的获奖答案: 更换
where _filters.Contains((string)sr.Element(\"itemtype\"))
where _filters.Any(filter => ((string)sr.Element(\"itemtype\")).Contains(filter))
    

解决方法

        尝试这个:
_filters.Any(s => ((string)sr.Element(\"itemtype\") ?? \"\").Contains(s))
这样,您可以检查元素的值是否包含
_filters
中的任何字符串。使用空合并运算符可确保在不存在
itemtype
节点时不抛出
NullReferenceException
,因为将其替换为空字符串。 另一种方法是使用ѭ10并滤除null:
var q = from sr in SearchResults.Descendants(\"Result\")
        let itemtype = (string)sr.Element(\"itemtype\")
        where itemtype != null &&
              _filters.Any(filter => itemtype.Contains(filter))
        orderby (string)sr.Element(\"ipitemtype\") ascending
        select new SearchItem
        {
            //Create Object
            ID = (string)sr.Element(\"blabla\")
        }
请注意,
String.Contains
区分大小写。因此,对\“视频\”的检查在\“视频\”上的大写\“ V \”不匹配。要忽略大小写,可以按以下方式使用
String.IndexOf
_filters.Any(filter => itemtype.IndexOf(filter,StringComparison.InvariantCultureIgnoreCase) >= 0)
    ,        您正在检查数组
_filters
是否具有值为
\"videos mission critial document advertising\"
的元素(不是这种情况),而不是检查
\"videos mission critial document advertising\"
是否包含
_filters
中的任何元素。 尝试这个:
where _filters.Any(filter => ((string)sr.Element(\"itemtype\")).Contains(filter))
    ,        问题是您对Contains方法的工作方式做出了错误的假设。 (另请参见
String.Contains()
文档,如果\“一个序列包含特定元素\”,则contains方法将返回true。在您描述的示例中,
_filters
数组和
itemtype
文本都包含字符串
videos
,但彼此都不包含。更多适当的测试将使用以下扩展方法:
public static class ContainsAnyExtension
{
    public static bool ContainsAny<T>(this IEnumerable<T> enumerable,params T[] elements)
    {
        if(enumerable == null) throw new ArgumentNullException(\"enumerable\");
        if(!enumerable.Any() || elements.Length == 0) return false;
        foreach(var element in elements){
           if(enumerable.Contains(element)){
               return true;
           }
        }
        return false;
    }
}
因此,正确的LINQ查询将是:
var q = from sr in SearchResults.Descendants(\"Result\")
        where ((string)sr.Element(\"itemtype\")).ContainsAny(_filters)
        orderby ((string)sr.Element(\"ipitemtype\")) ascending
        select new SearchItem
        {
            ID = sr.Element(\"blabla\").Value
        };
回顾这篇文章也可能会有所帮助:我如何使用LINQ Contains(string [])而不是Contains(string),后者类似,但是专门针对
String.Contains
方法而不是
Enumerable.Contains
扩展名。