Efficiently remove duplicate elements from the list I have a legacy code in which ids List has some duplicate value coming and this method is being called from lot of difference places as of now -
public async Task&lt;List&lt;T&gt;&gt; Execute&lt;T&gt;(IList&lt;int&gt; ids, Policy policy, Func&lt;CancellationToken, int, Task&lt;T&gt;&gt; mapperFunc) where T : class
{
    var holder = new List&lt;Task&lt;T&gt;&gt;(ids.Count);
    var removeNull = new List&lt;T&gt;(ids.Count);
    for (int i = 0; i &lt; ids.Count; i++)
    {
        var id = ids[i];
        holder.Add(ProcessData(policy, ct =&gt; mapperFunc(ct, id)));
    }

    var responses = await Task.WhenAll(holder);
    for (int i = 0; i &lt; responses.Length; i++)
    {
        var response = responses[i];
        if (response != null)
        {
            removeNull.Add(response);
        }
    }
    return removeNull;
}

I am trying to change above method such that I can remove duplicate stuff from ids list so I came up with below code which does that but I wanted to see if there is any better way we can write below code?
public async Task&lt;List&lt;T&gt;&gt; Execute&lt;T&gt;(IList&lt;int&gt; ids, Policy policy, Func&lt;CancellationToken, int, Task&lt;T&gt;&gt; mapperFunc) where T : class
{
    var noDupsList = new HashSet&lt;int&gt;(ids).ToList();
    var holder = new List&lt;Task&lt;T&gt;&gt;(noDupsList.Count);
    var removeNull = new List&lt;T&gt;(noDupsList.Count);
    for (int i = 0; i &lt; noDupsList.Count; i++)
    {
        var id = noDupsList[i];
        holder.Add(ProcessData(policy, ct =&gt; mapperFunc(ct, id)));
    }

    var responses = await Task.WhenAll(holder);
    for (int i = 0; i &lt; responses.Length; i++)
    {
        var response = responses[i];
        if (response != null)
        {
            removeNull.Add(response);
        }
    }
    return removeNull;
}

Update
Seeing the answer that came I thought it's good idea to mention how my actual code is - This is how my original code is :
public async Task&lt;List&lt;T&gt;&gt; Execute&lt;T&gt;(IList&lt;int&gt; ids, Policy policy, Func&lt;CancellationToken, int, Task&lt;T&gt;&gt; mapperFunc, string logMessage) where T : class
{
    var noDupsList = new HashSet&lt;int&gt;(ids).ToList();
    var holder = new List&lt;Task&lt;T&gt;&gt;(noDupsList.Count);
    var removeNull = new List&lt;T&gt;(noDupsList.Count);
    using (var logMetric = new LogMetric(_logger, TITLE, &quot;DatabaseCall&quot;))
    {
        logMetric.Message = logMessage;
        for (int i = 0; i &lt; noDupsList.Count; i++)
        {
            var id = noDupsList[i];
            holder.Add(ProcessData(policy, ct =&gt; mapperFunc(ct, id)));
        }

        var responses = await Task.WhenAll(holder);
        for (int i = 0; i &lt; responses.Length; i++)
        {
            var response = responses[i];
            if (response != null)
            {
                removeNull.Add(response);
            }
        }
        logMetric.StatusCode = (removeNull.Count == 0) ? 204 : 200;
    }
    return removeNull;
}
I think you used a good way to filter out the duplicates, but I don't see why you feel the need to call .ToList() after that. A HashSet is perfectly iterable.
As such, I believe I would write your lengthy code somewhat differently as:
public async Task&lt;IReadonlyList&lt;T&gt;&gt; Execute&lt;T&gt;(IEnumerable&lt;int&gt; ids, Policy policy, Func&lt;CancellationToken, int, Task&lt;T&gt;&gt; mapperFunc) where T : class 
{
    return (await Task.WhenAll(
            new HashSet&lt;int&gt;(ids).Select( id =&gt; ProcessData( policy, ct =&gt; mapperFunc( ct, id ) ) ) ) )
        .Where( response =&gt; response != null )
        .ToList();
}

It will still remove all the duplicates, await all entries using the Task.WhenAll and remove the null values.
As for knowing if it is more efficient I can't tell without testing. I think it is more readable, though to be fair, I would probably rather assign the results to a variable before filtering them out, saving you some brackets.
public async Task&lt;IReadonlyList&lt;T&gt;&gt; Execute&lt;T&gt;(IEnumerable&lt;int&gt; ids, Policy policy, Func&lt;CancellationToken, int, Task&lt;T&gt;&gt; mapperFunc) where T : class 
{
    var responses = await Task.WhenAll(
            new HashSet&lt;int&gt;(ids).Select( id =&gt; ProcessData( policy, ct =&gt; mapperFunc( ct, id ) ) ) );

    return responses
        .Where( response =&gt; response != null )
        .ToList();
}