What does [param: NotNull] mean in C#?

In Entity Framework's source code (link) I found this line:

public virtual IRelationalTransaction Transaction 
{ get; [param: NotNull] protected set; }

The [param: NotNull] part looks very strange to me. Any idea what kind of a C# syntax is this? I'm familiar with attributes and param but not this combination.

The definition of NotNull is this:

[AttributeUsage(
    AttributeTargets.Method | AttributeTargets.Parameter |
    AttributeTargets.Property | AttributeTargets.Delegate |
    AttributeTargets.Field)]
internal sealed class NotNullAttribute : Attribute
{
}

Which I expected to be used simply as [NotNull] but what is param doing here?


Solution 1:

When you mark method with NotNull it means, that method returns not null object:

[NotNull]
public object Get()
{
    return null; //error
}

When you mark setter it does the same - setter returns not null (because .net converts properties to get and set methods).

public virtual IRelationalTransaction Transaction { get; [NotNull] protected set; }

Equals to:

[NotNull] 
public virtual void set_Transaction(IRelationalTransaction value) { ... }

So, you need to add param: to point, that "i mean - parameter of setter is not null, not a result of set-method":

public virtual IRelationalTransaction Transaction { get; [param: NotNull] protected set; }

Equals to:

public virtual void set_Transaction([NotNull] IRelationalTransaction value) { ... }

Solution 2:

param: is the attribute target. See: Attribute specification

The attribute target can be one of these:

assembly, module, field, event, method, param, property, return, type

So [param: NotNull] means that the NotNullAttribute applies to the value parameter of the setter. It is necessary to specify the target here, since the value parameter does not appear as a method parameter explicitly.


A common use of the attribute-target is to specify the InternalsVisibleToAttribute in order to make types and members declared as internal visible to unit test projects.

[assembly:InternalsVisibleTo("UnitTestProject")]

The assembly does not appear as a language construct, therefore the attribute-target assembly is the only way to specify an attribute for the assembly. Btw: It can be specified in any source code file.