在foreach循环中将if-else转换为LINQ

时间:2018-08-10 16:40:04

标签: c# linq

我想要实现的是将这个foreach循环转换为LINQ等效项。当前代码循环浏览作为DB对象的通用对象IE List列表,然后根据对象类型创建本地对象。

 foreach (var message in messages)
 {
     if (message is TextMessageData)
     {
         output.Add(new TextMessage
         {
             Content = ((TextMessageData)message).Content,
             Sender = ((TextMessageData)message).Sender,
             TimeSent = ((TextMessageData)message).TimeSent
         });
     }
     else if(message is ImageDataRecord)
     {
         output.Add(new ImageMessage
         {
             ImageUrl = ((ImageDataRecord)message).Url,
             Sender = ((ImageDataRecord)message).Sender,
             TimeSent = ((ImageDataRecord)message).TimeSent
         });
     }
 }

到目前为止,我的代码看起来像这样,但是,我不确定如何为每个if语句条件返回结果集

var data = from message in messages
           where message is TextMessageData
           select new TextMessage
           {
               Content = ((TextMessageData)message).Content,
               Sender = ((TextMessageData)message).Sender,
               TimeSent = ((TextMessageData)message).TimeSent
           };

1 个答案:

答案 0 :(得分:2)

如何遵循这些思路:

var textMessages = messages.OfType<TextMessageData>().Select(m => (Message)new TextMessage() { … });
var imageMessages = messages.OfType<ImageDataRecord>().Select(m => (Message)new ImageMessage() { … });
var output = textMessages.Concat(imageMessages).ToList();

单行显示如下:

var output = messages.OfType<TextMessageData>()
                     .Select(m => (Message)new TextMessage() { … })
                     .Concat(messages.OfType<ImageDataRecord>()
                                     .Select(m => new ImageMessage() { … }))
                     .ToList();

另一种解决方案是“作弊”一点,然后将整个if语句放入lambda中,如下所示:

var output = messages.Where(message => message is TextMessageData || message is ImageDataRecord)
                     .Select(message =>
                     {
                         if (message is TextMessageData)
                         {
                             return (Message)new TextMessage
                             {
                                 …
                             };
                         }
                         else if (message is ImageDataRecord)
                         {
                             return new ImageMessage
                             {
                                 …
                             };
                         }
                         else
                             throw new Exception();
                     }).ToList();

只有在您有足够的内存将所有元素都保留在内存中并且多次访问元素的情况下,在LINQ语句末尾调用.ToList()才能创建实际的List<T>

还有许多其他方法可以减少代码量。例如,您可以考虑使用pattern matchingdeconstructingyield关键字:

IEnumerable<Message> ConvertMessages()
{
    foreach (var message in messages)
        if(message is TextMessageData tmd)
            yield return new TextMessage()
            {
                ImageUrl = tmd.Url,
                Sender = tmd.Sender,
                TimeSent = tmd.TimeSent
            }
        else if (message is ImageDataRecord ird)
            yield return new ImageMessage()
            {
                ImageUrl = ird.Url,
                Sender = ird.Sender,
                TimeSent = ird.TimeSent
            }
}

一个更重要的问题是,您是否必须首先进行转换。将对象从一种类型转换为另一种类型本身价值不大。浪费时间和内存。