#c# #performance #linq
#c# #Производительность #linq
Вопрос:
Как реструктурировать эти структуры данных и код обработки данных, чтобы использовать LINQ для краткости, ясности и эффективности использования ресурсов (процессор память)?
public class Account
{
public string AccountNumber {get; set;}
}
public class Customer
{
public List<Account> Accounts {get; set;}
}
public static void TransformAccount(Account account)
{
if (account != null amp;amp; account.AccountNumber != null)
{
account.AccountNumber = account.AccountNumber.Trim().TrimStart(new char[] {'0'});
}
}
public static void TransformCustomer(Customer customer)
{
if (customer == null || customer.Accounts == null) return;
foreach (var account in customer.Accounts)
{
TransformAccount(account);
}
}
public static ProcessCustomers(List<Customer> customers)
{
if (customers != null)
{
foreach (var customer in customers)
{
TransformCustomer(customer);
}
}
}
Комментарии:
1. К вашему сведению: Хотя использование Linq может помочь с удобочитаемостью кода и ремонтопригодностью, оно редко заставляет код выполняться быстрее или эффективнее по сравнению с эквивалентным циклом for / foreach / while.
2. И хотя LINQ отлично подходит для запросов к данным, он не предназначен для использования для изменения данных, как вы делаете здесь.
foreach
циклы обычно считаются правильным способом сделать это. По этой причине LINQ не предоставляетForEach
метод расширения.3. Я не вижу никаких улучшений, которые может внести linq, вы могли бы сделать что-то вроде:
customers .ForEach(x => { if x!= null) TransformCustomer(customer);});
но на самом деле это то же самое, только foreach (я думаю) должен быть еще медленнее.4.
and resource efficiency (cpu memory )
— как вы думаете, что именно делает LINQ? Вот код для LINQ.Where(...)
.
Ответ №1:
LINQ лучше подходит для запросов, чем для изменения данных. Тем не менее, вы могли бы использовать LINQ, чтобы получить элементы учетной записи, которые вы хотите изменить, и внести изменения в foreach.
var customers = GetCustomers(); // Some method that gets a customer list
var toModify = from customer in customers where customer.Accounts != null
from account in customer.Accounts where account.AccountNumber != null
select account;
foreach(var item in toModify)
item.AccountNumber = item.AccountNumber.Trim().TrimStart(new char[]{'0'});
Это не обязательно будет более производительным, чем просто использование циклов foreach, но вы можете счесть это более читабельным. Итак, хотя вы могли бы добиться краткости и ясности, я не думаю, что вы также получите производительность (как указано в комментариях).
Ответ №2:
Вот способ сделать это в LINQ.
При использовании фиктивного списка из 1000 клиентов с 1000 учетными записями в каждом ваш код с foreach занял 75 миллисекунд, а этот LINQ занял 123 миллисекунды, почти в два раза больше времени.
public static void ProcessCustomersLinq(List<Customer> customers)
{
customers?
.Where(c => c != null amp;amp; c.Accounts != null)
.SelectMany(c => c.Accounts.Where(a => a != null))
.ToList()
.ForEach(a => TrimAccountNumber(a));
}
private static void TrimAccountNumber(Account account)
{
account.AccountNumber = account.AccountNumber.Trim().TrimStart(new char[] { '0' });
}
Комментарии:
1. Рассмотрите возможность использования morelinq.github.io/2.8/ref/api/html / … чтобы избежать затрат на выделение памяти для
ToList
.