12

Consider the following code:

    public static void Foo()
    {
        Bar(null);
    }

    public static void Bar([NotNull] string s)
    {
        if (s == null)
            throw new ArgumentNullException("s");
    }

The [NotNull] attribute is used on Bar to tell callers that s shouldn't be null. This works fine, and I get a warning when I pass null to Bar (Possible 'null' assignment to entity marked with 'NotNull' attribute).

But it doesn't actually prevent me from passing null, so Bar must still check if s is null. So why am I also getting a warning on if (s == null) (Expression is always false) ?

As far as I can tell, this attribute has an ambiguous meaning; depending on context, it can mean two different things:

  • for the caller: don't pass a null argument
  • for the callee: this argument is not null

Am I using this attribute correctly, or am I missing something?

BTW, I'm using Resharper 7 EAP, so it might be a bug; however I want to make sure my usage is correct before I report it...


EDIT: just tried the same thing with R# 5.1 at work; it shows the warning on the call site, but not in the method. I'll report it on Jetbrain's Youtrack.


EDIT2: bug reported here

Thomas Levesque
  • 286,951
  • 70
  • 623
  • 758
  • What happens if you add a second caller which passes something other than `null`? Could be that v7 does more insightful value source analysis and sees that in this case the only caller of `Bar` passes `null`... – AakashM May 22 '12 at 08:11
  • btw as far as I know, the semantics of this attribute are *only* the first of your bullet points; it is a declaration by the method to the outside world. – AakashM May 22 '12 at 08:16
  • @AakashM, good point, but if it did this analysis, it should say "expression is always true", not always false... Anyway, I tried to add a call with a non-null value for s, and it still gives the same warning. – Thomas Levesque May 22 '12 at 10:04
  • Oh whoops, completely missed that it was the wrong way round! – AakashM May 22 '12 at 10:08

1 Answers1

3

As far as I can tell, you're using it right and ReSharper is wrong to tell you the comparison is always false. The [NotNull] attribute is no more than documentation and your code is right to double-check the input values. It wouldn't be the first time ReSharper made a wrong or stupid suggestion. The cool thing about JetBrains is that they have a public bug tracker where you can report this and get feedback straight from the devs.

That said, (and forgive me if you're aware of it), C# 4.0's Code Contracts makes this easy, predictable, and reliable:

Contract.RequiresAlways(s != null);
Tim Schmelter
  • 450,073
  • 74
  • 686
  • 939
Mahmoud Al-Qudsi
  • 28,357
  • 12
  • 85
  • 125