我是c#编程的新手,并且有以下场景。
我正在使用一个返回IEnumerable的API,我希望根据一些对象属性进行迭代:
IEnumerable<objects> listOfObjects = filter.getItems(id);
List<CustomObject> sortedList = new List<CustomObject>();
foreach (CustomObject obj in listOfObjects )
{
obj.Load(Load.Expanded);
sortedList.Add(obj);
}
foreach (CustomObject custObj in sortedList.OrderByDescending(c => c.RevisionDate))
{
// business logic
}
我需要执行以上所有操作,因为我无法对过滤器查询中返回的对象进行类型转换。此外,未加载从过滤器查询返回的对象,这意味着如果我不执行第一个foreach循环,则第二个foreach中的RevisionDate值将为null。
我想知道是否有更好的方法来处理这种情况,只需1次循环即可消除这些行数吗?
答案 0 :(得分:4)
你可以在一个linq语句中这样做:
foreach (var custObj in listOfObjects
.Cast<CustomObject>()
.Select(obj => {obj.Load(); return obj;})
.OrderByDescending(c => c.RevisionDate))
请注意,这种Select
的使用通常是不受欢迎的,并且不是一种非常好的做法(在obj.Load
中有Select
这样的副作用。
答案 1 :(得分:1)
您应该能够使用IEnumerable方法Select
。
请参阅文档here。
简而言之,你需要做这样的事情来消除第一个循环:
List<CustomObject> sortedList = filter.getItems(id).Select<object, CustomObject>(x =>
{
(CustomObject)x).Load(Load.Expanded);
return (CustomObject)x;
});
答案 2 :(得分:0)
Thera是C#库中的几个特殊结构,用于处理延迟初始化。每一个都可能有一些特殊性,可能更好或更差,符合你的需要。
第一个是System.Lazy<T>
类,而没有类开销System.Threading.LazyInitializer
和一堆静态方法,并提供特定于线程的数据System.Threading.ThreadLocal<T>
,效果更好。
Lazy<T>
的用法很简单:
// Initialize by using default Lazy<T> constructor. The
// Orders array itself is not created yet.
Lazy<Orders> _orders = new Lazy<Orders>();
// Initialize by invoking a specific constructor on Order which
// will be used when Value property is accessed
Lazy<Orders> _orders = new Lazy<Orders>(() => new Orders(100));
// Lazy<Orders> will create the array only if displayOrders is
// which will go through path where _orders.Value is accessed
if (displayOrders == true)
{
DisplayOrders(_orders.Value.OrderData);
}
else
{
// Don't waste resources getting order data.
}
您可以将lambda的对象传递给CustomObject
,而不是使用构造函数传递lambda。如果您努力获得最佳性能,请避免使用Linq并以程序方式执行此操作。
示例来自:Lazy Initialization Microsoft Docs,我为了清晰起见改变了评论,几乎可以直接应用于您的代码