2

I need a threadsafe implementation of list, so I created an override for all list functionality and implemented all (useful) Linq functions and surrounded them with a lock. The only Linq function that I fail to implement is Select.

This is what the Select function looks like in the Linq implementation

public static IEnumerable<TResult> Select<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, TResult> selector);

I try to override that. It can be seen that select requires to use T and TResult, but to override the list implementation I only have T. This is what I tried so far:

    public partial class ThreadSafeList<T> : List<T>
    {
        public object _lock = new object();      

        public IEnumerable<TResult> Select(Func<T, TResult> selector)
        {
            lock (_lock)
            {
                return System.Linq.Enumerable.Select(this, selector);
            }
        }
    }

But TResult does not exist. Any ideas on how I can override the Linq Select implementation?

Pavel Anikhouski
  • 21,776
  • 12
  • 51
  • 66
HdG
  • 53
  • 7
  • 2
    I'm not entirely sure that what you are writing is actually as thread safe as you think. You may want to look into how LINQ generally uses deferred execution. In summary it won't be processing your selector in your lock which I suspect is what you are expecting. Instead it will wait until you start iterating over your IEnumerable and evaluate the selector then. Its hard to say for sure whether you are happy with this but its certainly something to bear in mind if you aren't already aware of it. – Chris Jan 28 '20 at 11:10
  • Thanks for your comment. I was not aware of that, but you are definitely right. I think I will go with this: https://stackoverflow.com/a/5874474/6297069. Or would ToList() be sufficient? – HdG Jan 28 '20 at 11:27
  • I'm not sure really what your requirements are. As the comments on that answer say there are a few sorts of thread safety. Its for you to decide what would be sufficient for your purposes... – Chris Jan 28 '20 at 14:18

1 Answers1

4

You should make your Select method generic as well, by adding TResult generic type argument

public IEnumerable<TResult> Select<TResult>(Func<T, TResult> selector)
{
    lock (_lock)
    {
        return System.Linq.Enumerable.Select(this, selector);
    }
}

But keep in mind, that Select method is an extension method actually. System.Linq also uses deferred execution, you can evaluate result into list using ToList() method before return it, like that

using System.Linq;
...
public IEnumerable<TResult> Select<TResult>(Func<T, TResult> selector)
{
    lock (_lock)
    {
        return Enumerable.Select(this, selector).ToList();
    }
}
Pavel Anikhouski
  • 21,776
  • 12
  • 51
  • 66