C# 序列包含多个匹配元素
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18202686/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Sequence contains more than one matching element
提问by NoviceToDotNet
When I am trying to set IsDefault
property of each dressing items where match a condition it throws an error saying:
当我尝试设置IsDefault
与条件匹配的每个敷料项目的属性时,它会抛出一个错误:
Sequence contains more than one matching sequence.
序列包含多个匹配序列。
(this.DressingItems
.Where(xx => xx.DressingInfo.CatID == catId
&& xx.ProductID == this.ProductID)
.Single()).IsDefault = false;
采纳答案by Damith
this.DressingItems.Where(x=> x.DressingInfo.CatID == catId &&
x.ProductID == this.ProductID).ToList()
.ForEach(item=>item.IsDefault = false);
回答by Rohit
It is an InvalidOperationException
thrown by the Single
method.
它是InvalidOperationException
由Single
方法抛出的。
The method is supposed to return only one element, please check the criteria that you use on your query.
该方法应该只返回一个元素,请检查您在查询中使用的标准。
However an exception is also thrown when it fails to find any element
但是当它找不到任何元素时也会抛出异常
回答by Rex
you have more than one item in this.DressingItems that match the given CatId and Product Id.
您在 this.DressingItems 中有多个与给定 CatId 和 Product Id 匹配的项目。
if you are sure there must be one (single), then you have to review how is this.DressingItems loaded.
如果您确定必须有一个(单个),那么您必须查看 this.DressingItems 是如何加载的。
if it's expected there are more than one, then you have to use foreach to set the values.
如果预计有多个,那么您必须使用 foreach 来设置值。
回答by Matten
Well, this exception says that at least two items of the sequence DressingItems
match your Where
condition. The call to Single
then causes the exception because it asserts that only one item is passed in.
好吧,这个例外说明序列DressingItems
中至少有两个项目符合您的Where
条件。对Single
then的调用会导致异常,因为它断言只传入了一项。
Reading your question makes me think that you want to do something on each item of the input sequence, so you will probably use a foreach loop:
阅读您的问题让我觉得您想对输入序列的每个项目执行某些操作,因此您可能会使用 foreach 循环:
foreach(var item in this.DressingItems.Where(xx => xx.DressingInfo.CatID == catId && xx.ProductID == this.ProductID))
{
item.IsDefault = false;
}
回答by Yannick Motton
The point of the Single
operator is to assert that a given sequence only has one item. For instance when retrieving a specific instance by primary key.
该点Single
经营者断言,一个给定的顺序只有一个项目。例如,当通过主键检索特定实例时。
I suppose you want to mutate the state of any DressingItem
matching the criteria, in which case you have some options, all involving enumerating the resultset, and executing some behavior.
我想你想改变任何DressingItem
匹配条件的状态,在这种情况下你有一些选择,所有这些都涉及枚举结果集,并执行一些行为。
There is no LINQ operator to specifically do this, since LINQ operators are meant to be pure. Pure functions are functions that do not have side effects, and this is exactly what you are trying to do.
没有 LINQ 运算符专门执行此操作,因为 LINQ 运算符是纯运算符。纯函数是没有副作用的函数,这正是您想要做的。
There is, however, an extensionmethod on List<T>
which does allow this. e.g.
然而,有一个扩展List<T>
方法确实允许这样做。例如
this.DressingItems.Where(di => di.DressingInfo.CatID == catId
&& di.ProductID == this.ProductID)
.ToList()
.ForEach(di =>
{
di.IsDefault = false
});
Or you could roll your own:
或者你可以推出自己的:
public static class EnumerableExtensions
{
public static IEnumerable<T> ForEach<T>(
this IEnumerable<T> source,
Action<T> mutator)
{
var buffered = source.ToList();
buffered.ForEach(mutator);
return buffered;
}
}
You might ask why the guys at Microsoft decided against adding this to the BCL: As I recall, the idea was that an extensionmethod vs. a foreach() { }
construct would not yield much benefits in terms of typing anyway, and it wouldn't help at all in terms of ambiguity. All other operators are side-effect free, and this one is explicitely designed to induce them.
你可能会问为什么微软的人决定不把它添加到 BCL:我记得,这个想法是,扩展方法与foreach() { }
结构无论如何都不会在打字方面产生太多好处,而且它根本没有帮助歧义条款。所有其他运算符都没有副作用,而这个运算符是明确设计来诱导它们的。
回答by Default
Since you are looking for a one liner, you could create your own method doing that.
由于您正在寻找单衬里,您可以创建自己的方法来做到这一点。
public static void DoActionForEachElement<T>(IEnumerable<T> items, Func<T, bool> predicate, Action<T> action)
{
foreach (var item in items)
{
if (predicate(item))
action(item);
}
}
and then call it by
然后调用它
DoActionForEachElement(
DressingItems,
xx => xx.DressingInfo.CatID == catId && xx.ProductID == ProductID,
x => x.IsDefault = false);
This way you don't have to cast the result from Where
to a List
first.
这样,您就不必从把结果Where
到List
第一。