C# 包含Linq to XML Where子句中的功能
Linq to XML中where子句的.Contains()函数出现意外行为。它的功能似乎与字符串函数中的“==”not Contains()类似 例如:C# 包含Linq to XML Where子句中的功能,c#,.net,linq-to-xml,C#,.net,Linq To Xml,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
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"),
}
_筛选器是字符串的列表。假设它包含3个值:
_filters[0] = "videos";
_filters[1] = "documents";
_filters[2] = "cat pictures";
现在的情况是,如果
<itemtype>videos</itemtype>
与
试试这个:
_filters.Any(s => ((string)sr.Element("itemtype") ?? "").Contains(s))
where _filters.Any(filter => ((string)sr.Element("itemtype")).Contains(filter))
通过这种方式,您可以检查元素的值是否包含\u过滤器中的任何字符串。使用null合并运算符可确保当itemtype
节点不存在时不会引发NullReferenceException
,因为它被替换为空字符串
另一种方法是使用let
并过滤掉空值:
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)
您正在检查数组\u过滤器
是否有值为的元素“videos mission Critical document advertising”(并非如此),而不是“videos mission Critical document advertising”
是否包含\u过滤器中的任何元素
试试这个:
_filters.Any(s => ((string)sr.Element("itemtype") ?? "").Contains(s))
where _filters.Any(filter => ((string)sr.Element("itemtype")).Contains(filter))
问题是你对方法的工作方式做出了错误的假设。(另请参见contains方法,如果“序列包含特定元素”,则返回true。在您描述的示例中,\u过滤器
数组和项目类型
文本都包含字符串视频
,但两者都不包含。更合适的测试是使用以下扩展方法:
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;
}
}
查看此帖子也可能会有所帮助:,它类似于但专门针对字符串。Contains
方法,而不是可枚举。Contains
扩展。我不认为这是真的,如果节点包含单个值,如videos,那么Linq会返回该节点,而不是来自_filters.interest的字符串。因此我尝试了你的代码,现在我遇到了相反的问题。只是视频的节点被忽略,而像营销传播视频这样的节点被接受。真的很困惑。如果结果是null
,使用Contains
,这里会抛出NullReferenceException
。我已经更新了我的响应来处理这个问题塞纳里奥。请查看我的新答案-原来的答案是错误的。ContainsAny现在对我来说不是一个可用的选项。如果这有什么不同,我将使用Silverlight,但我检查了一下以确保我的.NET framework是版本4。@Wesley,你说它不可用是什么意思?我发布了代码。复制并粘贴到你的解决方案中。@smartcaveman当一个简单的LINQ语句可以完成任务时,这是一个非常麻烦的过程。我做了,ContainsAny显示“字符串不包含ContainsAny的定义”。我现在正在研究这个问题。@Ahmad Mageed你指的是一个单独的LINQ语句。这就是我现在正在做的,但是使用两个语句,其中一个带有正确的where,似乎很愚蠢。我的问题是,如果项没有正确标记,有时可能是空的。如果元素为空,即。Value抛出异常,这就是为什么我总是对字符串进行大小写,而不是依赖于.Value。@Wesley尝试更新的方法。这使用let
保留显式转换结果,如果该结果为空,则将其过滤掉,然后对照过滤项进行检查。**EDIT我尝试了该方法,枚举结果完全为空。不是真的,结果为空有一些结果,但不是全部。@Wesley在你发表评论之前,我在文章底部又添加了一个更新。你的过滤器或值可能包含大小写混合。使用我上面概述的IndexOf
方法忽略过滤器和元素值的大小写。如果这不起作用,那么问题就出在别处。艾哈迈德,确实有一个案例问题是另一个团队糟糕代码的一部分。这个问题已经解决,所有XML都设置为小写。你的解决方案有效,但其他人的速度更快,他们的代码更干净,所以我将他们的代码标记为答案。不过我会投票,你做得很好。
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;
}
}
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
};