嗨,假设这两种方法:
private List<IObjectProvider> GetProviderForType(Type type)
{
List<IObjectProvider> returnValue = new List<IObjectProvider>();
foreach (KeyValuePair<Type, IObjectProvider> provider in _objectProviders)
{
if ((provider.Key.IsAssignableFrom(type) ||
type.IsAssignableFrom(provider.Key)) &&
provider.Value.SupportsType(type))
{
returnValue.Add(provider.Value);
}
}
return returnValue;
}
private IEnumerable<IObjectProvider> GetProviderForType1(Type type)
{
foreach (KeyValuePair<Type, IObjectProvider> provider in _objectProviders)
if ((provider.Key.IsAssignableFrom(type) ||
type.IsAssignableFrom(provider.Key)) &&
provider.Value.SupportsType(type))
yield return provider.Value;
}
哪一个更快?当我查看第一种方法时,我看到内存是为List分配的,我认为不需要它。 IEnumerable 方法对我来说似乎更快。
例如,假设你打电话
int a = GetProviderForType(myType).Count;
int b = GetProviderForType1(myType).Count();
现在,另一个问题是,这两个之间是否有性能差异?
您怎么看?
答案 0 :(得分:30)
在这种特殊情况下,使用IEnumerable<T>
表单会更有效率,因为仅需要知道计数。如果你不需要,那么存储数据,调整缓冲区大小等没有意义。
如果您因任何原因需要再次使用结果,List<T>
表格会更有效。
请注意,Count()
扩展方法和Count
属性对List<T>
都有效,因为Count()
的实现会检查目标序列是否实现{{}如果是,请使用ICollection<T>
属性。
另一个应该是更多效率的选项(尽管只是)只会调用带有委托的Count
的重载:
Count
这将避免private int GetProviderCount(Type type)
{
return _objectProviders.Count(provider =>
(provider.Key.IsAssignableFrom(type)
|| type.IsAssignableFrom(provider.Key))
&& provider.Value.SupportsType(type));
}
和Where
条款带来的额外级别的间接。
(正如Marc所说,对于少量数据,性能差异无论如何都可能微不足道。)
答案 1 :(得分:4)
对此类问题的准确答案可能会因许多因素而异,并且可能会随着CLR的发展而进一步变化。确定的唯一方法是测量它 - 并记住,如果与显示的操作相比差异很小,那么你应该选择最易读,可维护的编写方式。
在这方面,您可能还想尝试:
private IEnumerable<IObjectProvider> GetProviderForType1(Type type)
{
return _objectProviders.Where(provider =>
provider.Key.IsAssignableFrom(type) ||
type.IsAssignableFrom(provider.Key)) &&
provider.Value.SupportsType(type))
.Select(p => p.Value);
}
如果要将结果“快照”到列表中,还可以返回IEnumerable<T>
然后使用ToList
扩展方法,为自己提供很大的灵活性。如果需要多次检查,这将避免重复评估代码以生成列表。
答案 2 :(得分:4)
这个问题的一个重要部分是“数据有多大”?多少行...
对于少量数据,列表很好 - 分配足够大的列表需要花费的时间可以忽略不计,并且不会多次调整大小(没有,如果你能告诉它有多大的话)。< / p>
但是,这不会扩展到庞大的数据量;您的提供商似乎不太可能支持数以千计的接口,因此我不会说它是必要来使用此模型 - 但它不会造成太大的伤害。
当然,您也可以使用LINQ:
return from provider in _objectProviders
where provider.Key.IsAssignableFrom(type) ...
select provider.Value;
这也是推迟的yield
方法......
答案 3 :(得分:2)
IEnumerable和IList之间的主要区别:
IEnumerable的: 实现MoveNext,重置,获取当前方法并返回一类IEnumerator以进行迭代 通过记录。
IList:暴露IEnumerable接口以及它也是非泛型对象的集合,可以通过索引访问所以IEnumerable + ICollection(操作数据)和添加,删除,插入(在特定的索引处)都是有用的IList实施的方法。在查看你的Code In My Opinion后,IEnumerable更有效,但如果你想对数据进行一些操作,返回列表也很有用,如果你只想迭代数据,那么IEnumerable是更好的。