Mig*_*lla 2 c# linq lazy-loading deferred-execution
在阅读了一些如何使用,foreach,linq延迟执行和迭代器在C#中工作之后.我决定尝试在一个小项目中优化基于属性的验证机制.结果:
private IEnumerable<string> GetPropertyErrors(PropertyInfo property)
{
// where Entity is the current object instance
string propertyValue = property.GetValue(Entity)?.ToString();
foreach (var attribute in property.GetCustomAttributes().OfType<ValidationAttribute>())
{
if (!attribute.IsValid(propertyValue))
{
yield return $"Error: {property.Name} {attribute.ErrorMessage}";
}
}
}
// inside another method
foreach(string error in GetPropertyErrors(property))
{
// Some display/insert log operation
}
Run Code Online (Sandbox Code Playgroud)
我觉得这很慢,但也可能是由于反射或大量的属性要处理.
所以我的问题是...... 这是最优还是很好地利用了延迟加载机制?或者我错过了什么,只是浪费了大量的资源.
注意:代码意图本身并不重要,我关心的是在其中使用延迟加载.
延迟加载不是C#或Entity Framework特有的.这是一种常见的模式,允许延迟一些数据加载.延期意味着不立即加载.有些样品需要时:
延迟加载并不总是意味着在您确实需要数据之前推迟加载.在您真正需要该数据之前,可能会在后台线程中进行加载.例如,您可能永远不会滚动到网页底部以查看页脚图像.延迟加载意味着只能推迟.C#枚举器可以帮助您.考虑获取目录中的文件列表:
string[] files = Directory.GetFiles("D:");
IEnumerable<string> filesEnumerator = Directory.EnumerateFiles("D:");
Run Code Online (Sandbox Code Playgroud)
第一种方法返回文件数组.这意味着目录应该获取其所有文件并将其名称保存到数组,然后才能获得第一个文件名.这就像在看到文档之前加载所有图像一样.
第二种方法使用枚举器 - 当您要求下一个文件名时,它会逐个返回文件.这意味着立即返回枚举器而不获取所有文件并将它们保存到某个集合中.并且您可以在需要时逐个处理文件.这里获取文件列表是推迟的.
但你应该小心.如果不延迟基础操作,那么返回枚举器将不会给您带来任何好处.例如
public IEnumerable<string> EnumerateFiles(string path)
{
foreach(string file in Directory.GetFiles(path))
yield return file;
}
Run Code Online (Sandbox Code Playgroud)
在这里,您使用GetFiles在返回文件名之前填充文件名数组的方法.所以逐个产生文件会给你带来速度上的好处.
在你的情况下,你有完全相同的问题 - GetCustomAttributes扩展内部使用Attribute.GetCustomAttributes返回属性数组的方法.所以你不会减少获得第一个结果的时间.