我可以使用 LINQ 有条件地创建 IEnumerable 吗?
我必须遵循以下代码:
List<Obj> coll = new List<Obj>();
if (cond1) coll.Add(new Obj { /*...*/ });
if (cond2) coll.Add(new Obj { /*...*/ });
if (cond3) coll.Add(new Obj { /*...*/ });
有没有办法为此使用 LINQ 或集合初始值设定项?
编辑:
我想在这里使用集合初始值设定项的原因是因为我有一个对象树,我使用初始值设定项和 LINQ 对其进行了完全初始化。这个地方是唯一一个不遵循这一原则的地方。
var myobj = new MyBigObj
{
Prop1 = from .. select ..,
Prop2 = from .. select ..,
...
Prop3 = new MySmallerObj
{
PropSmall1 = from .. select ..,
PropSmall2 = from .. select ..,
...
}
};
现在这根本不适合我的方案:
List<Obj> coll = new List<Obj>();
if (cond1) coll.Add(new Obj { /*...*/ });
if (cond2) coll.Add(new Obj { /*...*/ });
if (cond3) coll.Add(new Obj { /*...*/ });
myobj.Prop4 = coll;
当然我可以将此代码放在一个返回 IEnumerable 的单独函数中并调用它..:)
EDIT2:
看来我必须编写一些扩展代码我会这样调用的方法:
new Obj[0]
.ConditionalConcat(cond1, x=>new Obj { /*...*/ })
.ConditionalConcat(cond2, x=>new Obj { /*...*/ })
.ConditionalConcat(cond3, x=>new Obj { /*...*/ })
I have to following code:
List<Obj> coll = new List<Obj>();
if (cond1) coll.Add(new Obj { /*...*/ });
if (cond2) coll.Add(new Obj { /*...*/ });
if (cond3) coll.Add(new Obj { /*...*/ });
Is there a way to use LINQ or collection initializers for that?
EDIT:
The reason I want to use a collection initializer here is because I have an object tree which I do completely initialize with initialiers and LINQ. This spot is the only one which doesn't follow this principle.
var myobj = new MyBigObj
{
Prop1 = from .. select ..,
Prop2 = from .. select ..,
...
Prop3 = new MySmallerObj
{
PropSmall1 = from .. select ..,
PropSmall2 = from .. select ..,
...
}
};
And now this simply doesn't fit in my scheme:
List<Obj> coll = new List<Obj>();
if (cond1) coll.Add(new Obj { /*...*/ });
if (cond2) coll.Add(new Obj { /*...*/ });
if (cond3) coll.Add(new Obj { /*...*/ });
myobj.Prop4 = coll;
Sure I could put this code in a separate function that returns IEnumerable and call that.. :)
EDIT2:
It looks like I have to code some extension method which I would call like:
new Obj[0]
.ConditionalConcat(cond1, x=>new Obj { /*...*/ })
.ConditionalConcat(cond2, x=>new Obj { /*...*/ })
.ConditionalConcat(cond3, x=>new Obj { /*...*/ })
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
一个相当可怕的选择:
它并不比原始代码简单;)(而且它无条件创建所有值 - 它只是有条件将它们包含在集合中。)
编辑:仅在需要时构造值的替代方案:
编辑:鉴于您请求的语法,这是一个相当简单的选项:
使用扩展方法:
One fairly horrible option:
It's not exactly simpler than the original code though ;) (And also it unconditionally creates all the values - it's only conditionally including them in the collection.)
EDIT: An alternative which only constructs the values when it needs to:
EDIT: Given your requested syntax, this is a fairly easy option:
with an extension method:
如果您的条件取决于单个状态对象(或可以简化为的对象),
您可以使用yield 创建一个方法,如下所示:
通过这种方式,您可以将
IEnumerable
生成逻辑与使用者逻辑分开。If your conditions depend on a single status object (or something that can reduced to),
you can create a method using yield, like the following:
In this way, you will separate the
IEnumerable<Obj>
generation logic, from the consumer logic.老问题,但这是使用三元运算符
的另一种方法? :
、.Concat()
和Enumerable.Empty()
Old question, but here is another approach using ternery operators
? :
, .Concat()
andEnumerable.Empty<T>()
虽然是一个老问题,但我可以选择以某种清晰的方式解决它,而无需扩展或任何其他方法。
假设要创建的条件和初始对象集合具有相同的大小,我使用索引 Where 重载方法,所以它不是有条件地添加对象,而是过滤它们,使用 funcs/lambdas 我们也会变得懒惰,如果我们想。
对象的实际创建并不相关,所以我只对整数进行装箱(您可以将其替换为实际创建,即使用索引从另一个集合中获取它们),列表操作用于取回整数 - 但值集合已经有 2元素,所以所有这些都可以被丢弃(也许除了使用 func 调用的 select 之外,以防使用懒惰)。
中运行示例测试的所有代码
以下是在 MSVS UPD. 。
这里还有带有“获取对象”的惰性和非惰性俏皮话
Though an old question, but I have an option to solve it in a somewhat clear way and without extensions or any other methods.
Assuming that conditions and initial collection of objects to be created are of same size, I used indexed Where overload approach, so it is not adding objects conditionally, but rather filtering them, with a use of funcs/lambdas we get also laziness, if we want.
The actual creation of objects is not relevant, so I put just boxing of ints (you could replace it with real creation, i.e. getting them from another collection using index), and list manipulation is for getting ints back - but values collection already has 2 elements, so all this could be thrown away (maybe except select with func call in case of using laziness).
Here is the all the code for running sample test right in MSVS
UPD.
Here also lazy and non-lazy one-liners with "getting object"