0

I want to know which approach is faster. I have the following class:

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; }
}

I have a list of AccountBalance data as List<AccountBAlance> and I want to transform data in a way that I want to separate AccountMediaBalance collection in one list, All tokens in one list and all passes in a separate list.

There are two approaches for doing this:

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();
    }
}

The other approach would be like following:

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>());
        }
    }
}

Performance is a big concern. Can anyone put me in the right direction and let me know which approach is faster and why?

Muhammad Qasim
  • 1,574
  • 13
  • 25
  • 4
    What stops you from running a test on it? Fill the lists with a few million items and clock the runtime. This will at least give you the timing benchmark. Apart from that, if the `tokens` and `passes` are independent try running them in parallel. – Markus Deibel May 28 '19 at 09:19
  • For me this is a duplicate of https://stackoverflow.com/questions/3156059/is-a-linq-statement-faster-than-a-foreach-loop?rq=1 "LINQ also uses for loop" so "LINQ will be a bit slower because it introduces overhead" – yawnobleix May 28 '19 at 09:23

1 Answers1

0

foreach loop uses GetEnumerator directly, while linq creates the query object first and then GetEnumerator. So it is naturally a little bit faster to use foreach loop for a single iteration but it still makes the code look better to use linq.

Alsein
  • 3,459
  • 13
  • 30