Search code examples
c#.netentity-frameworkienumerable

How can I call a function expecting `params T[]` arguments given an `IEnumerable<T>`?


How can I call a function expecting param T[] arguments given an IEnumerable<T>?

Consider the following function signature:

public async Task AddNotificationRecordsAsync(
               IEnumerable<NotificationRecord> notificationRecords,
               CancellationToken cancellationToken = default)

In this function, I want to call the following EF Core function:

void DbSet<NotificationRecord>.AddRange(params NotificationRecord[] entities)

However, I don't know how to convert the IEnumerable into separate params.

In Python, I would use the unpacking operator "*" as follows: f(*mylist).


Solution

  • How can I call a function expecting param T[] arguments given an IEnumerable?

    The param keyword allows you to pass an array as separate parameters. But it does not prohibit you to pass a regular array.

    This is demonstrated in this example:

    using System;
                        
    public class Program
    {
        static void f(params int[] vals)
        {
            foreach (int val in vals) Console.Write(val + ",");
            Console.WriteLine("");
        }
    
        public static void Main()
        {
            f(1, 2, 3);  // works
            f(new int[3] { 1, 2, 3 }); // also works
        }
    }
    

    Live demo

    Therefore you can use Enumerable.ToArray method to convert IEnumerable<T> to T[] and pass it to a method expecting a param T[]:

    public async Task AddNotificationRecordsAsync(IEnumerable<NotificationRecord> notificationRecords, CancellationToken cancellationToken = default)
    {
       // ...
    
       //---------------------------------vvvvvvvvvvvvvvvvvvvvvvvvvvvvv--
       DbSet<NotificationRecord>.AddRange(notificationRecords.ToArray());
    }
    

    A side note:
    In this specific case, as @shingo commented, DbSet<TEntity>.AddRange also has an overload that accepts IEnumerable<TEntity>. Therefore you could have passed notificationRecords as is.