我在测试代码中看到了这个循环:
foreach ( StuffId Id in Result.GetIdList() )
{
if ( Id.Level == 3 )
{
Level3Id = Id.ToString();
}
if ( Id.Level == 5 )
{
Level5Id = Id.ToString();
}
}
其他测试意味着每个级别只有一个Id,或者当每个级别有多个时,那么Id将是相同的。
现在对LINQ略显痴迷,我首先重构了这个:
IEnumerable<StuffId> Ids = Result.GetIdList();
Level3Id = Ids.Where( x => x.Level == 3 ).First().Id.ToString();
Level5Id = Ids.Where( x => x.Level == 5 ).First().Id.ToString();
然后代码重复困扰了我,所以我重构了这个:
IEnumerable<StuffId> Ids = Result.GetIdList();
Func<int,string> IdFromLevel =
level => Ids.Where( x => x.Level == level ).First().Id.ToString();
Level3Id = IdFromLevel(3);
Level5Id = IdFromLevel(5);
一位同事想知道为什么我没有用代替代表的方法。我的推理是一个方法会稍微“混乱”,因为我必须另外传入集合,并且使用委托对于简单的测试来说没什么大不了的(简洁的,可读的,没有分支是好的品质)。
当然,我看了SO,发现了这个看似相关的问题:
C#: Func<> instead of methods?
其中共识似乎倾向于代表委托方法。在我的情况下这同样适用吗?
答案 0 :(得分:0)
这是一个重用的问题。如果您使用的方法可能在其他情况下可重复使用,则应单独定义它们 但是如果你只有另外变化的短语句,你应该坚持使用匿名函数/ lambda表达式,这些可能会导致更好的运行时行为。
来自SO:
您发布的代码没有任何优势。在您的代码中,使用委托只会增加复杂性以及额外的运行时成本 - 因此您最好直接调用该方法。
然而,代表有很多用途。 “传递”到其他方法是主要用法,虽然存储函数并在以后使用它也非常有用。
LINQ完全基于这个概念。当你这样做时:
var results = myCollection.Where(item => item == "Foo");
您将委托(定义为lambda:item =&gt; item ==“Foo”)传递给LINQ库中的Where
函数。这是使它正常工作的原因。
答案 1 :(得分:0)
不确定利弊,但阅读这些文章可能会帮助您做出更好的决定:
http://msdn.microsoft.com/en-in/library/bb549151.aspx
http://msdn.microsoft.com/en-us/library/orm-9780596516109-03-09.aspx
答案 2 :(得分:0)
我会选择第一个区块:
foreach (StuffId Id in Result.GetIdList())
{
if (Id.Level == 3)
{
Level3Id = Id.ToString();
}
if (Id.Level == 5)
{
Level5Id = Id.ToString();
}
}
这只会将集合循环一次。我看到你不担心这里的性能,但对我而言,这不是性能或优化问题。这是一个以逻辑上正确的方式做事的问题。如果可以一步完成,为什么要做两次(如果可读性没有受到伤害)。
额外的好处是你没有Func<,>
和方法之间的困境,以及相关的复杂性。至于字符的数量或键入的容易程度,它几乎相同,除了你是水平(在第二种情况下)而不是垂直写。您甚至可以在foreach
块内的两行中编写上述内容。
如果您一心想分开编写这两个动作,我会根据在这种情况下该函数是否与当前方法的范围之外的相关性做出选择。在我看来,它是一个微不足道的谓词,只与两个任务相关。所以我喜欢:
var Ids = Result.GetIdList();
Func<int, string> IdFromLevel = level => Ids.Single(x => x.Level == level).Id.ToString();
Level3Id = IdFromLevel(3);
Level5Id = IdFromLevel(5);
首先Single
优先于First
..