Ручной цикл foreach быстрее или запрос linq для коллекций в следующем сценарии? - PullRequest
0 голосов
/ 28 мая 2019

Я хочу знать, какой подход быстрее.У меня есть следующий класс:

public class AccountBalance
{       
    public long AccountID { get; set; }
    public string AccountNumber { get; set; }

    [NotRequiredForDataTable]        
    public IEnumerable<AccountMediaBalance> AccountMediaBalances { get; set; }       
}

public class AccountMediaBalance
{
    public long AccountID { get; set; }
    public long MediaID { get; set; }
    public string MediaSerialNumber { get; set; } 
    public decimal? CashAmount { get; set; }
    public int FareID { get; set; }
    public bool ShowID { get; set; }
    public bool ShareCash { get; set; }
    public bool ShareToken { get; set; }
    public bool SharePass { get; set; }
    public IEnumerable<Token> Tokens { get; set; }
    public IEnumerable<Pass> Passes { get; set; }
}  

public class Token
{
    public long TokenID { get; set; } 
    public long AccountID { get; set; }        
    public long MediaProductID { get; set; }
    public long MediaID { get; set; }
    public long? ActivateByMediaID { get; set; }
    public string SerialNumber { get; set; }
    public decimal? TransferValue { get; set; }
    public DateTimeOffset CreateTime { get; set; }
    public DateTimeOffset? ActivateTime { get; set; }
    public DateTimeOffset? ExpiryTime { get; set; }
}    

public class Pass
{
    public long MediaProductID { get; set; }
    public long AccountID { get; set; }
    public long MediaID { get; set; }        
    public int ProductID { get; set; }
    public long? ActivateByMediaID { get; set; }
    public string SerialNumber { get; set; }
    public DateTimeOffset CreateTime { get; set; }
    public DateTimeOffset? ActivateTime { get; set; }
    public DateTimeOffset? ExpiryTime { get; set; }
}

У меня есть список AccountBalance данных как List<AccountBAlance>, и я хочу преобразовать данные так, чтобы я хотел разделить коллекцию AccountMediaBalance в один список,Все tokens в одном списке и все passes в отдельном списке.

Для этого есть два подхода:

public void SaveAccountBalances(List<AccountBalance> accountBalances)
{
    if (accountBalances != null)
    {
        var mediaBalances = accountBalances.SelectMany(x => x.AccountMediaBalances ?? 
                            Enumerable.Empty<AccountMediaBalance>()).ToList();

        var tokens = mediaBalances.SelectMany(x => x.Tokens ?? Enumerable.Empty<Token>()).ToList();

        var passes = mediaBalances.SelectMany(x => x.Passes ?? Enumerable.Empty<Pass>()).ToList();
    }
}

Другой подход будет выглядеть следующим образом:

public void SaveAccountBalances(List<AccountBalance> accountBalances)
{
    var mediaBalances = new List<AccountMediaBalance>();
    var tokens = new List<Token>();
    var passes = new List<Pass>();

    if (accountBalances != null)
    {
        foreach (var item in accountBalances)
        {
            mediaBalances.AddRange(item.AccountMediaBalances ?? Enumerable.Empty<AccountMediaBalance>());
        }

        foreach (var item in mediaBalances)
        {
            tokens.AddRange(item.Tokens ?? Enumerable.Empty<Token>());
            passes.AddRange(item.Passes ?? Enumerable.Empty<Pass>());
        }
    }
}

Производительность - большая проблема.Кто-нибудь может направить меня в правильном направлении и сообщить, какой подход быстрее и почему?

1 Ответ

0 голосов
/ 28 мая 2019
Цикл

foreach напрямую использует GetEnumerator, в то время как linq сначала создает объект запроса, а затем GetEnumerator. Так что, естественно, немного быстрее использовать цикл foreach для одной итерации, но он все равно делает код лучше, используя linq.

...