quadroid
quadroid

Reputation: 8950

ReSharper wrongly claims that IDictionary.Values is always non null

I got the following Code:

    public IEnumerator<TRow> GetEnumerator()
    {
        if (this._rows.Values == null) return Enumerable.Empty<TRow>().GetEnumerator();

        return this._rows.Values.GetEnumerator();
    }

Resharper tells me that _rows.Values is always non null (which is not the case because the implementation of IDictionary I use - PostSharps AdvisableDictionary from here http://doc.postsharp.net/t_postsharp_patterns_collections_advisabledictionary_2) tends to return null right after creation (very awkward implementation i guess - i dont know why they implemented it this way).

enter image description here

Whatever Implementation of IDictionary I use - Why does ReSharper expect the Implementation to work that way? Nobody can guarantee that this is true. Or did i get something wrong ?

As requested in the Comments: A minimal Implementation that shows the behavior (set a breakpoint on the return Enumerable.Empty<TRow>().GetEnumerator() which is grayed out by resharper):

 class Program
{
    static void Main(string[] args)
    {
        var model = new Model();

        bool any = model.Any();
    }
}

[NotifyPropertyChanged]
public class Model : IEnumerable<string>
{
    private IDictionary<string, string> dictionary;

    public Model()
    {
        dictionary = new AdvisableDictionary<string, string>();
    }

    public IEnumerator<string> GetEnumerator()
    {
        if (dictionary.Values == null) return Enumerable.Empty<string>().GetEnumerator();
        return dictionary.Values.GetEnumerator();
    }

    IEnumerator IEnumerable.GetEnumerator()
    {
        return GetEnumerator();
    }
}

this example requires the PostSharp.Patterns.Model package and a PostSharp License (there is a trial available) OR swap the AdvisableDictionaryfor a custom dictionary that returns null on the Values getter.

Upvotes: 1

Views: 132

Answers (2)

xanatos
xanatos

Reputation: 111930

In newer referencesource Microsoft added some codecontract that covers IDictionary<,>:

// Returns a collections of the values in this dictionary.
ICollection<TValue> IDictionary<TKey, TValue>.Values {
    get {
        Contract.Ensures(Contract.Result<ICollection<TValue>>() != null);
        return default(ICollection<TValue>);
    }
}

From this contract it is quite clear that Values mustn't be null (note that it is a mustn't, not a can't :-) Broken implementations of IDictionary<,> can return null and it won't be catched by the runtime).

Upvotes: 4

Oliver Heil
Oliver Heil

Reputation: 64

It is always true because .Values always returns something (Collection out of Values). If your Dictionary should be empty, the Values-Collection is also empty. If the dictionary is null, there will be a NullPointerException since values do not refer to any object.

Upvotes: 1

Related Questions