是否可能延迟加载&在单次迭代中键入Cast对象?

时间:2017-10-23 15:03:46

标签: c# linq foreach

我是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次循环即可消除这些行数吗?

3 个答案:

答案 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,我为了清晰起见改变了评论,几乎可以直接应用于您的代码