Question: I know from C# 8, reference type are non-nullable by default, and we can turn on NRT in the project file. I saw code like this:

```
static void ThrowIfNull([NotNull] string? x)
{
    if (x == null)
    {
        throw new ArgumentNullException();
    }
}

```

I don't know what's the point to use `[NotNull]` in the parameter. It is like telling the compiler that:

"x is guaranteed to never be null if the method returns without throwing an exception"

But why the compiler need this information? if we do:

```
static void ThrowIfNull(string? x)
{
    if (x == null)
    {
        throw new ArgumentNullException();
    }
}

```

the code produces no warning since we do a null check

Answer: 
The Attribute is for the caller of the method.
The C# compiler will more or less limit the scope of nullability analysis to the current method and the signatures of called methods.

In other words, if the calling method looks like this:

```
static void Caller()
{
  string? str = GetString();
  ThrowIfNull(str);
  Console.WriteLine(str.ToUpper());
}

```

there should be a compiler warning that .ToUpper() is a possible NRE.
If you, however, decorate the attribute, the compiler will know that the normal return of the ThrowIfNull method implies that str is not null and the warning should be fixed.

An alternative way to propagate this info would be to make ThrowIfNull() return the string if it's not null. Then you could do this:

```
static void Caller()
{
  string? str = GetString();
  var str2 = ThrowIfNull(str);
  Console.WriteLine(str2.ToUpper());
}

```
You should not use `[NotNull]` when using `?` syntax to declare nullability (and Nullability annotations are enabled), because that's actually the same, or in your case, contradictory. Either the string is not-null (then you don't need the `?`) or it can be null then add the `?` but not the `[NotNull]` attribute. The NotNull-Attribute is deprecated when nullability annotations are enabled, because the compiler actually internally does the same based of the use of the question mark specifier.

There are some attributes that you might still (rarely) need, such as `[NotNullWhen()]`, but otherwise don't mix Nullability attributes with nullability annotations.