Search code examples
c#collectionssynchronizedcollection

Is it valid to add `null` to a SynchronizedCollection - documentation error and/or removed restriction?


Per SynchronizedCollection.Add, an ArgumentException is thrown when "The value set is null or is not of the correct generic type T for the collection". ReSharper 8 also considers this a [NotNull] parameter.

However, there is no exception when running the following code in LINQPad:

new SynchronizedCollection<string>().Add((string)null);

Furthermore, inspection of SynchronizedCollection.Add reveals it delegates down to List.Insert which does not have this limitation. ("The object to insert. The value can be null for reference types."

Given this conflicting information and behavior, is it valid to add null to a SynchronizedCollection?

Did it used to be the case that adding a null value would have raised an exception?


Solution

  • It is a documentation error. The exception only happens on IList.Add(object) (or any other IList method) not the normal Add(T).

    Also the error only happens if T is a value type and you pass in null, it does not happen for non value types.

    From the Reference Source

    public class SynchronizedCollection<T> : IList<T>, IList
    {
        //...
    
        int IList.Add(object value)
        {
            VerifyValueType(value);
    
            lock (this.sync)
            {
                this.Add((T)value);
                return this.Count - 1;
            }
        }
    
        //...
    
        static void VerifyValueType(object value)
        {
            if (value == null)
            {
                if (typeof(T).IsValueType)
                {
                    throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.SynchronizedCollectionWrongTypeNull)));
                }
            }
            else if (!(value is T))
            {
                throw DiagnosticUtility.ExceptionUtility.ThrowHelperError(new ArgumentException(SR.GetString(SR.SynchronizedCollectionWrongType1, value.GetType().FullName)));
            }
        }
    }
    

    If you look at the error info

    The value set is null or is not of the correct generic type T for the collection

    That situation is not possible with Add(T) you will get a compiler error instead of a runtime error. You could only pass in a non correct generic type if the parameter was of type object to get the run-time exception of ArgumentException.