Limitations

edit

Declarations

  • Only the supported underlying types can be wrapped. An ID wraps a single value: there are no composite IDs.
  • No generic IDs, and no IDs nested in a generic type (MFSTID0004).
  • The type and its containing types must be partial.
  • The generic attribute needs .NET 10 or later. On older targets, use [StronglyTypedId(typeof(int))]. See Declaring IDs.

Behavior

  • The default value of a struct ID is not validated. default(ProjectId) wraps 0 without calling your constructor. See Validate the value.
  • Records keep their own equality and ToString. The StringComparison and GenerateToStringAsRecord options have no effect on a record or a record struct, whose Equals, GetHashCode and ToString are written by the compiler. Use a struct or a class when you need these options.
  • StringComparison applies to equality only. Sorting string IDs uses Comparer<string>.Default, which depends on the current culture.
  • The IFormatProvider is ignored. Parsing and formatting always use the invariant culture.

Integrations

  • System.Text.Json source generation ignores the generated converter. With a JsonSerializerContext, which Native AOT applications use, an ID is serialized as {}. See System.Text.Json.
  • No Entity Framework Core converter is generated. Write one value converter per ID type. See Entity Framework Core.
  • The converters are private. They are registered by attributes on the ID, and you cannot add them to JsonSerializerOptions.Converters or reuse them in another type.