Attributes

attributes #direction: right #spacing: 10 #gravity: .8 #arrowSize: 4 #title: attributes [Attribute|Represents the base class for custom attributes.] [AttributeUsageAttribute|Specifies the usage of another attribute class. This class cannot be inherited.] [ThreadStaticAttribute| Indicates that the value of a static field is unique for each thread.] [FlagsAttribute|Indicates that an enumeration can be treated as a bit field\; that is, a set of flags.] [Attribute] <:- [<note>Serialization Related] - [SerializableAttribute|Indicates that a class can be serialized using binary or XML serialization. This class cannot be inherited.] [Attribute] <:- [<note>Threading Related] [<note>Serialization Related] - [NonSerializedAttribute|Indicates that a field of a serializable class should not be serialized. This class cannot be inherited.] [<note>Threading Related] - [STAThreadAttribute|Indicates that the COM threading model for an application is single-threaded apartment (STA).] [<note>Threading Related] - [MTAThreadAttribute|Indicates that the COM threading model for an application is multithreaded apartment (MTA).] [<note>Threading Related] - [ThreadStaticAttribute] [Attribute] <:- [AttributeUsageAttribute] [Attribute] <:- [FlagsAttribute] [Attribute] <:- [<note>Development related] - [ObsoleteAttribute|Marks the program elements that are no longer in use. This class cannot be inherited.] [<note>Development related] - [CallerMemberNameAttribute|Allows you to obtain the method or property name of the caller to the method.] [<note>Development related] - [CallerLineNumberAttribute|Allows you to obtain the line number in the source file at which the method is called.] [<note>Development related] - [CallerFilePathAttribute|Allows you to obtain the full path of the source file that contains the caller. This is the file path at the time of compile.] [<note>Development related] - [CallerArgumentExpressionAttribute|Indicates that a parameter captures the expression passed for another parameter as a string.] Attribute Represents the base class for custom attributes. AttributeUsageAttribute Specifies the usage of another attribute class. This class cannot be inherited. ThreadStaticAttribute Indicates that the value of a static field is unique for each thread. FlagsAttribute Indicates that an enumeration can be treated as a bit field; that is, a set of flags. Serialization Related SerializableAttribute Indicates that a class can be serialized using binary or XML serialization. This class cannot be inherited. Threading Related NonSerializedAttribute Indicates that a field of a serializable class should not be serialized. This class cannot be inherited. STAThreadAttribute Indicates that the COM threading model for an application is single-threaded apartment (STA). MTAThreadAttribute Indicates that the COM threading model for an application is multithreaded apartment (MTA). Development related ObsoleteAttribute Marks the program elements that are no longer in use. This class cannot be inherited. CallerMemberNameAttribute Allows you to obtain the method or property name of the caller to the method. CallerLineNumberAttribute Allows you to obtain the line number in the source file at which the method is called. CallerFilePathAttribute Allows you to obtain the full path of the source file that contains the caller. This is the file path at the time of compile. CallerArgumentExpressionAttribute Indicates that a parameter captures the expression passed for another parameter as a string.

Common Attributes

Data annotation

attributes-dataannotation #direction: right #spacing: 10 #gravity: .8 #arrowSize: 4 #title: attributes-dataannotation [Attribute|Represents the base class for custom attributes.] [ValidationAttribute|Serves as the base class for all validation attributes.] [DisplayAttribute|Provides a general-purpose attribute that lets you specify localizable strings for types and members of entity partial classes.] [DisplayFormatAttribute|Specifies how data fields are displayed and formatted by ASP.NET Dynamic Data.] [Attribute] <:- [ValidationAttribute] [Attribute] <:- [DisplayAttribute] [Attribute] <:- [DescriptionAttribute] [Attribute] <:- [DisplayFormatAttribute] [DescriptionAttribute|Specifies a description for a property or event.] [ValidationAttribute] <:- [AllowedValuesAttribute|Specifies a list of values that should be allowed in a property.] [ValidationAttribute] <:- [Base64StringAttribute|Specifies that a data field value is a well-formed Base64 string.] [ValidationAttribute] <:- [CompareAttribute|Provides an attribute that compares two properties.] [ValidationAttribute] <:- [CustomValidationAttribute|Specifies a custom validation method that is used to validate a property or class instance.] [ValidationAttribute] <:- [DeniedValuesAttribute|Specifies a list of values that should not be allowed in a property.] [ValidationAttribute] <:- [LengthAttribute|Specifies the minimum and maximum length of collection/string data allowed in a property.] [ValidationAttribute] <:- [MaxLengthAttribute|Specifies the maximum length of array or string data allowed in a property.] [ValidationAttribute] <:- [MinLengthAttribute|Specifies the minimum length of array or string data allowed in a property.] [ValidationAttribute] <:- [RangeAttribute|Specifies the numeric range constraints for the value of a data field.] [ValidationAttribute] <:- [RegularExpressionAttribute|Specifies that a data field value in ASP.NET Dynamic Data must match the specified regular expression.] [ValidationAttribute] <:- [StringLengthAttribute|Specifies the minimum and maximum length of characters that are allowed in a data field.] [ValidationAttribute] <:- [DataTypeAttribute|Specifies the name of an additional type to associate with a data field.] [DataTypeAttribute] <:- [CreditCardAttribute|Specifies that a data field value is a credit card number.] [DataTypeAttribute] <:- [EmailAddressAttribute|Validates an email address.] [DataTypeAttribute] <:- [EnumDataTypeAttribute|Enables a .NET enumeration to be mapped to a data column.] [DataTypeAttribute] <:- [FileExtensionsAttribute|Validates file name extensions] [DataTypeAttribute] <:- [PhoneAttribute|Specifies that a data field value is a well-formed phone number.] [DataTypeAttribute] <:- [UrlAttribute|Provides URL validation.] Attribute Represents the base class for custom attributes. ValidationAttribute Serves as the base class for all validation attributes. DisplayAttribute Provides a general-purpose attribute that lets you specify localizable strings for types and members of entity partial classes. DisplayFormatAttribute Specifies how data fields are displayed and formatted by ASP.NET Dynamic Data. DescriptionAttribute Specifies a description for a property or event. AllowedValuesAttribute Specifies a list of values that should be allowed in a property. Base64StringAttribute Specifies that a data field value is a well-formed Base64 string. CompareAttribute Provides an attribute that compares two properties. CustomValidationAttribute Specifies a custom validation method that is used to validate a property or class instance. DeniedValuesAttribute Specifies a list of values that should not be allowed in a property. LengthAttribute Specifies the minimum and maximum length of collection/string data allowed in a property. MaxLengthAttribute Specifies the maximum length of array or string data allowed in a property. MinLengthAttribute Specifies the minimum length of array or string data allowed in a property. RangeAttribute Specifies the numeric range constraints for the value of a data field. RegularExpressionAttribute Specifies that a data field value in ASP.NET Dynamic Data must match the specified regular expression. StringLengthAttribute Specifies the minimum and maximum length of characters that are allowed in a data field. DataTypeAttribute Specifies the name of an additional type to associate with a data field. CreditCardAttribute Specifies that a data field value is a credit card number. EmailAddressAttribute Validates an email address. EnumDataTypeAttribute Enables a .NET enumeration to be mapped to a data column. FileExtensionsAttribute Validates file name extensions PhoneAttribute Specifies that a data field value is a well-formed phone number. UrlAttribute Provides URL validation.

Data annotation Attributes

Creating custom attributes

All custom attributes must inherit from the System.Attribute class. This is the foundation that allows the attribute to be recognized by the .NET runtime.

  • The attribute class must end with the name Attribute
  • The attribute class must be annotated with the AttributeUsage attribute, which determines how a custom attribute class can be used.
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = false, AllowMultiple = false)]
public class MyCustomAttribute : Attribute
{
    public string Description { get; }
    public int Version { get; }

    // Constructor to initialize the attribute
    public MyCustomAttribute(string description, int version)
    {
        Description = description;
        Version = version;
    }
}

In the above example the MyCustomAttribute is restricted to be used on methods and classes. The Inherited = false prevents the attribute from being inherited by derived classes. The AllowMultiple = false ensures that the attribute can only be applied once per element.

Attributes interpreted by the C# compiler

Obsolete

It is used to mark program elements (like classes, methods, properties, etc.) as outdated or no longer recommended for use. The [Obsolete] attribute is typically applied to warn developers when they use a deprecated feature.

[Obsolete("Use NewMethod instead.")]
public static void OldMethod()
{
    Console.WriteLine("This is the old method.");
}

During compile if any method calls the OldMethod() code, then a compiler warning will be produced with the message Use NewMethod instead.

Experimental

Available since C# 12. It is used to indicate an experimental feature. The compiler issues a warning if you access a method or type annotated with the [Experimental] attribute. It is used to communicate that the feature is in a trial phase and not yet stable.

SetsRequiredMembers

The [SetsRequiredMembers] attribute informs the compiler that a constructor sets all required members in that class or struct. The compiler assumes any constructor with the SetsRequiredMembers attribute initializes all required members.

ModuleInitializer

The [ModuleInitializer] attribute marks a method that the runtime calls when the assembly loads. The ModuleInitializer attribute can only be applied to a method that:

  • Is static.
  • Is parameterless.
  • Returns void.
  • Is accessible from the containing module, that is, internal or public.
  • Isn't a generic method.
  • Isn't contained in a generic class.
  • Isn't a local function.

The ModuleInitializer attribute can be applied to multiple methods. In that case, the order in which the runtime calls them is deterministic but not specified.

using System.Runtime.CompilerServices;

internal static class Program
{
    [ModuleInitializer]
    public static void BeforeMain()
    {
        Console.WriteLine("This is executed before main");
    }

    private static void Main(string[] args)
    {
        Console.WriteLine("Main");
    }
}

OverloadResolutionPriority

The [OverloadResolutionPriority] attribute enables library authors to prefer one overload over another when two overloads can be ambiguous. Its primary use case is for library authors to write better performing overloads while still supporting existing code without breaks.

[OverloadResolutionPriority(1)]
public void M(params ReadOnlySpan<int> s) => Console.WriteLine("Span");
// Default overload resolution priority of 0
public void M(params int[] a) => Console.WriteLine("Array");

Overload resolution considers the two methods equally good for some argument types. For an argument of int[], it prefers the first overload. To get the compiler to prefer the ReadOnlySpan version, you can increase the priority of that overload. This way, when the user types in M( into the editor, the void M(params ReadOnlySpan<int> s) version will be suggested by the IntelliSense first.

Nullable attributes

In a nullable enabled context, the compiler performs static analysis of code to determine the null-state of all reference type variables:

  • not-null: Static analysis determines that a variable has a non-null value.
  • maybe-null: Static analysis can't determine that a variable is assigned a non-null value.

Attributes can be aplied to our code that gives the compiler more information about the rules for your API. When calling code is compiled in a nullable enabled context, the compiler will warn callers when they violate those rules. These attributes don't enable more checks on your implementation.

Preconditions: AllowNull and DisallowNull

  • AllowNull: A non-nullable parameter, field, or property may be null.
  • DisallowNull: A nullable parameter, field, or property should never be null.
[AllowNull]
public string ScreenName
{
    get => _screenName;
    set => _screenName = value ?? GenerateRandomScreenName();
}
private string _screenName = GenerateRandomScreenName();

[DisallowNull]
public string? ReviewComment
{
    get => _comment;
    set => _comment = value ?? throw new ArgumentNullException(nameof(value), "Cannot set to null");
}
string? _comment;

Postconditions: MaybeNull and NotNull

  • MaybeNull: A non-nullable parameter, field, property, or return value may be null.
  • NotNull: A nullable parameter, field, property, or return value will never be null.
[return: MaybeNull]
public T Find<T>(IEnumerable<T> sequence, Func<T, bool> predicate)
{
    //implementation
}

public static void ThrowWhenNull([NotNull] object? value, string valueExpression = "")
{
    _ = value ?? throw new ArgumentNullException(nameof(value), valueExpression);
}

Conditional post-conditions: NotNullWhen, MaybeNullWhen, and NotNullIfNotNull

  • NotNullWhen: A nullable argument won't be null when the method returns the specified bool value.
  • MaybeNullWhen: A non-nullable argument may be null when the method returns the specified bool value.
  • NotNullIfNotNull: A return value, property, or argument isn't null if the argument for the specified parameter isn't null.
bool TryGetMessage(string key, [NotNullWhen(true)] out string? message)
{
    if (_messageMap.ContainsKey(key))
        message = _messageMap[key];
    else
        message = null;
    return message is not null;
}

[return: NotNullIfNotNull(nameof(url))]
string? GetTopLevelDomainFromFullUrl(string? url)
{
    //implementation
}

MemberNotNull and MemberNotNullWhen

  • MemberNotNull: The listed member won't be null when the method returns.
  • MemberNotNullWhen: The listed member won't be null when the method returns the specified bool value.
public class Container
{
    private string _uniqueIdentifier; // must be initialized.
    private string? _optionalMessage;

    public Container()
    {
        Helper();
    }

    public Container(string message)
    {
        Helper();
        _optionalMessage = message;
    }

    [MemberNotNull(nameof(_uniqueIdentifier))]
    private void Helper()
    {
        _uniqueIdentifier = DateTime.Now.Ticks.ToString();
    }
}

DoesNotReturn and DoesNotReturnIf

  • DoesNotReturn: A method or property never returns. In other words, it always throws an exception.
  • DoesNotReturnIf: A method or property never returns if the associated bool parameter has the specified value.
[DoesNotReturn]
private void FailFast()
{
    throw new InvalidOperationException();
}

public void SetState(object containedField)
{
    if (containedField is null)
    {
        FailFast();
    }

    // containedField can't be null:
    _field = containedField;
}