工作中出现了一个讨论:
我们有一个包含 IList 的类。 Fact 是一个抽象基类,还有几个具体的子类(PopulationFact、GdpFact 等)。
最初我们会以这种方式查询给定的事实,即按类型:
.Facts.FirstOrDefault(x => x.Year == 2011 && x is GdpFact)
然而,现在提出了一个问题,我们是否应该引入 FactType 枚举来代替
.Facts.FirstOrDefault(x => x.Year == 2011 && x.FactType == FactType.Gdp)
之所以提出这个建议,是因为它据说更快。我承认我没有编写任何测试来尝试辨别性能差异,但我有两个问题:
1) 这样的“查询类型”本质上是不好的吗?
2) 考虑到事实是强类型的,添加 FactType 枚举不是多余的吗?
更新 澄清一下,这是 LINQ to objects 和 GdpFact:Fact。
更新 2 我们使用当前的典型数据(4 个事实)进行了测量,结果如下:
枚举查找:0.29660000000000003 毫秒 查找类型:0.24530000000000002 毫秒
所以在这种情况下类型查找更快!我会仔细选择我接受的答案。
最佳答案
我做过测试,我的1000000次迭代的结果大约是
ByCast 166ms
ByType 84ms
ByEnum 98ms
所以 enum
实际上是多余的,而且速度较慢,但幅度不大。这应该不足为奇,类型系统是 .Net Framework 的基础。
下面是测试代码,对错误表示歉意
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
class Program
{
private enum TypeOfFact
{
Gdp,
Other
}
private abstract class Fact
{
public virtual int Year { get; set; }
public abstract TypeOfFact FactType { get; }
}
private class GdpFact : Fact
{
public override TypeOfFact FactType
{
get { return TypeOfFact.Gdp; }
}
}
private class OtherFact : Fact
{
public override TypeOfFact FactType
{
get { return TypeOfFact.Other; }
}
}
static void Main()
{
Ilist<Fact> facts = new List<Fact>
{
new GdpFact { Year = 2010 },
new OtherFact { Year = 2010 },
new GdpFact { Year = 2009 },
new OtherFact { Year = 2009 },
new GdpFact { Year = 2011 },
new OtherFact { Year = 2011 },
};
const int interations = 1000000;
var funcs = new List<Func<IList<Fact>, Fact>>
{
ByList,
ByType,
ByEnum
};
// Warmup
foreach (var func in funcs)
{
Measure(5, func, facts);
}
// Results
foreach (var result in funcs.Select(f => new
{
Description = f.Method.Name,
Ms = Measure(iterations, f, facts)
}))
{
Console.WriteLine(
"{0} time = {1}ms",
result.Description,
result.Ms);
}
}
private static long Measure(
int iterations,
Func<IList<Fact>, Fact> func,
IList<Fact> facts)
{
var stopwatch = new Stopwatch();
stopwatch.Start();
for (var i = 0; i < iterations; i++)
{
func.Invoke(facts);
}
stopwatch.Stop();
return stopwatch.ElapsedMilliseconds;
}
private static Fact ByType(IList<Fact> facts)
{
return facts.FirstOrDefault(f =>
f.Year == 2011 && f is GdpFact);
}
private static Fact ByEnum(IList<Fact> facts)
{
return facts.FirstOrDefault(f =>
f.Year == 2011 && f.FactType == TypeOfFact.Gdp);
}
private static Fact ByCast(IList<Fact> facts)
{
return facts.OfType<GdpFact>()
.FirstOrDefault(f => f.Year == 2011);
}
}
这question似乎相关。
关于c# - Linq 查询的性能(按类型),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13609343/