Annotate System.ComponentModel.DataAnnotations for nullability (#39611)
authorShay Rojansky <roji@roji.org>
Tue, 28 Jul 2020 15:04:00 +0000 (18:04 +0300)
committerGitHub <noreply@github.com>
Tue, 28 Jul 2020 15:04:00 +0000 (18:04 +0300)
35 files changed:
src/libraries/System.ComponentModel.Annotations/ref/System.ComponentModel.Annotations.cs
src/libraries/System.ComponentModel.Annotations/ref/System.ComponentModel.Annotations.csproj
src/libraries/System.ComponentModel.Annotations/src/System.ComponentModel.Annotations.csproj
src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/AssociatedMetadataTypeTypeDescriptionProvider.cs
src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/AssociatedMetadataTypeTypeDescriptor.cs
src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/AssociationAttribute.cs
src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/CompareAttribute.cs
src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/CreditCardAttribute.cs
src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/CustomValidationAttribute.cs
src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/DataTypeAttribute.cs
src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/DisplayAttribute.cs
src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/DisplayColumnAttribute.cs
src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/DisplayFormatAttribute.cs
src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/EmailAddressAttribute.cs
src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/EnumDataTypeAttribute.cs
src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/FileExtensionsAttribute.cs
src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/FilterUIHintAttribute.cs
src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/LocalizableString.cs
src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/MaxLengthAttribute.cs
src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/MinLengthAttribute.cs
src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/PhoneAttribute.cs
src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/RangeAttribute.cs
src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/RegularExpressionAttribute.cs
src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/RequiredAttribute.cs
src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/Schema/ColumnAttribute.cs
src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/Schema/TableAttribute.cs
src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/StringLengthAttribute.cs
src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/UIHintAttribute.cs
src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/UrlAttribute.cs
src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/ValidationAttribute.cs
src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/ValidationAttributeStore.cs
src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/ValidationContext.cs
src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/ValidationException.cs
src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/ValidationResult.cs
src/libraries/System.ComponentModel.Annotations/src/System/ComponentModel/DataAnnotations/Validator.cs

index 1747a8c..4db1cfd 100644 (file)
@@ -6,12 +6,15 @@
 
 namespace System.ComponentModel.DataAnnotations
 {
+// TODO-NULLABLE: Enable after System.ComponentModel.TypeDescriptionProvider is annotated
+#nullable disable
     public partial class AssociatedMetadataTypeTypeDescriptionProvider : System.ComponentModel.TypeDescriptionProvider
     {
         public AssociatedMetadataTypeTypeDescriptionProvider(System.Type type) { }
         public AssociatedMetadataTypeTypeDescriptionProvider(System.Type type, System.Type associatedMetadataType) { }
         public override System.ComponentModel.ICustomTypeDescriptor GetTypeDescriptor(System.Type objectType, object instance) { throw null; }
     }
+#nullable enable
     [System.AttributeUsageAttribute(System.AttributeTargets.Field | System.AttributeTargets.Property, AllowMultiple=false, Inherited=true)]
     [System.ObsoleteAttribute("This attribute is no longer in use and will be ignored if applied.")]
     public sealed partial class AssociationAttribute : System.Attribute
@@ -29,7 +32,7 @@ namespace System.ComponentModel.DataAnnotations
     {
         public CompareAttribute(string otherProperty) { }
         public string OtherProperty { get { throw null; } }
-        public string OtherPropertyDisplayName { get { throw null; } }
+        public string? OtherPropertyDisplayName { get { throw null; } }
         public override bool RequiresValidationContext { get { throw null; } }
         public override string FormatErrorMessage(string name) { throw null; }
         protected override System.ComponentModel.DataAnnotations.ValidationResult IsValid(object value, System.ComponentModel.DataAnnotations.ValidationContext validationContext) { throw null; }
@@ -43,7 +46,7 @@ namespace System.ComponentModel.DataAnnotations
     public sealed partial class CreditCardAttribute : System.ComponentModel.DataAnnotations.DataTypeAttribute
     {
         public CreditCardAttribute() : base (default(System.ComponentModel.DataAnnotations.DataType)) { }
-        public override bool IsValid(object value) { throw null; }
+        public override bool IsValid(object? value) { throw null; }
     }
     [System.AttributeUsageAttribute(System.AttributeTargets.Class | System.AttributeTargets.Field | System.AttributeTargets.Method | System.AttributeTargets.Parameter | System.AttributeTargets.Property, AllowMultiple=true)]
     public sealed partial class CustomValidationAttribute : System.ComponentModel.DataAnnotations.ValidationAttribute
@@ -52,7 +55,7 @@ namespace System.ComponentModel.DataAnnotations
         public string Method { get { throw null; } }
         public System.Type ValidatorType { get { throw null; } }
         public override string FormatErrorMessage(string name) { throw null; }
-        protected override System.ComponentModel.DataAnnotations.ValidationResult IsValid(object value, System.ComponentModel.DataAnnotations.ValidationContext validationContext) { throw null; }
+        protected override System.ComponentModel.DataAnnotations.ValidationResult? IsValid(object? value, System.ComponentModel.DataAnnotations.ValidationContext validationContext) { throw null; }
     }
     public enum DataType
     {
@@ -79,11 +82,11 @@ namespace System.ComponentModel.DataAnnotations
     {
         public DataTypeAttribute(System.ComponentModel.DataAnnotations.DataType dataType) { }
         public DataTypeAttribute(string customDataType) { }
-        public string CustomDataType { get { throw null; } }
+        public string? CustomDataType { get { throw null; } }
         public System.ComponentModel.DataAnnotations.DataType DataType { get { throw null; } }
-        public System.ComponentModel.DataAnnotations.DisplayFormatAttribute DisplayFormat { get { throw null; } protected set { } }
+        public System.ComponentModel.DataAnnotations.DisplayFormatAttribute? DisplayFormat { get { throw null; } protected set { } }
         public virtual string GetDataTypeName() { throw null; }
-        public override bool IsValid(object value) { throw null; }
+        public override bool IsValid(object? value) { throw null; }
     }
     [System.AttributeUsageAttribute(System.AttributeTargets.Class | System.AttributeTargets.Field | System.AttributeTargets.Method | System.AttributeTargets.Parameter | System.AttributeTargets.Property, AllowMultiple=false)]
     public sealed partial class DisplayAttribute : System.Attribute
@@ -91,30 +94,30 @@ namespace System.ComponentModel.DataAnnotations
         public DisplayAttribute() { }
         public bool AutoGenerateField { get { throw null; } set { } }
         public bool AutoGenerateFilter { get { throw null; } set { } }
-        public string Description { get { throw null; } set { } }
-        public string GroupName { get { throw null; } set { } }
-        public string Name { get { throw null; } set { } }
+        public string? Description { get { throw null; } set { } }
+        public string? GroupName { get { throw null; } set { } }
+        public string? Name { get { throw null; } set { } }
         public int Order { get { throw null; } set { } }
-        public string Prompt { get { throw null; } set { } }
-        public System.Type ResourceType { get { throw null; } set { } }
-        public string ShortName { get { throw null; } set { } }
+        public string? Prompt { get { throw null; } set { } }
+        public System.Type? ResourceType { get { throw null; } set { } }
+        public string? ShortName { get { throw null; } set { } }
         public bool? GetAutoGenerateField() { throw null; }
         public bool? GetAutoGenerateFilter() { throw null; }
         public string GetDescription() { throw null; }
-        public string GetGroupName() { throw null; }
-        public string GetName() { throw null; }
+        public string? GetGroupName() { throw null; }
+        public string? GetName() { throw null; }
         public int? GetOrder() { throw null; }
-        public string GetPrompt() { throw null; }
-        public string GetShortName() { throw null; }
+        public string? GetPrompt() { throw null; }
+        public string? GetShortName() { throw null; }
     }
     [System.AttributeUsageAttribute(System.AttributeTargets.Class, Inherited=true, AllowMultiple=false)]
     public partial class DisplayColumnAttribute : System.Attribute
     {
         public DisplayColumnAttribute(string displayColumn) { }
-        public DisplayColumnAttribute(string displayColumn, string sortColumn) { }
-        public DisplayColumnAttribute(string displayColumn, string sortColumn, bool sortDescending) { }
+        public DisplayColumnAttribute(string displayColumn, string? sortColumn) { }
+        public DisplayColumnAttribute(string displayColumn, string? sortColumn, bool sortDescending) { }
         public string DisplayColumn { get { throw null; } }
-        public string SortColumn { get { throw null; } }
+        public string? SortColumn { get { throw null; } }
         public bool SortDescending { get { throw null; } }
     }
     [System.AttributeUsageAttribute(System.AttributeTargets.Field | System.AttributeTargets.Property, AllowMultiple=false)]
@@ -123,11 +126,11 @@ namespace System.ComponentModel.DataAnnotations
         public DisplayFormatAttribute() { }
         public bool ApplyFormatInEditMode { get { throw null; } set { } }
         public bool ConvertEmptyStringToNull { get { throw null; } set { } }
-        public string DataFormatString { get { throw null; } set { } }
+        public string? DataFormatString { get { throw null; } set { } }
         public bool HtmlEncode { get { throw null; } set { } }
-        public string NullDisplayText { get { throw null; } set { } }
-        public System.Type NullDisplayTextResourceType { get { throw null; } set { } }
-        public string GetNullDisplayText() { throw null; }
+        public string? NullDisplayText { get { throw null; } set { } }
+        public System.Type? NullDisplayTextResourceType { get { throw null; } set { } }
+        public string? GetNullDisplayText() { throw null; }
     }
     [System.AttributeUsageAttribute(System.AttributeTargets.Field | System.AttributeTargets.Property, AllowMultiple=false, Inherited=true)]
     public sealed partial class EditableAttribute : System.Attribute
@@ -140,14 +143,14 @@ namespace System.ComponentModel.DataAnnotations
     public sealed partial class EmailAddressAttribute : System.ComponentModel.DataAnnotations.DataTypeAttribute
     {
         public EmailAddressAttribute() : base (default(System.ComponentModel.DataAnnotations.DataType)) { }
-        public override bool IsValid(object value) { throw null; }
+        public override bool IsValid(object? value) { throw null; }
     }
     [System.AttributeUsageAttribute(System.AttributeTargets.Field | System.AttributeTargets.Method | System.AttributeTargets.Parameter | System.AttributeTargets.Property, AllowMultiple=false)]
     public sealed partial class EnumDataTypeAttribute : System.ComponentModel.DataAnnotations.DataTypeAttribute
     {
         public EnumDataTypeAttribute(System.Type enumType) : base (default(System.ComponentModel.DataAnnotations.DataType)) { }
         public System.Type EnumType { get { throw null; } }
-        public override bool IsValid(object value) { throw null; }
+        public override bool IsValid(object? value) { throw null; }
     }
     [System.AttributeUsageAttribute(System.AttributeTargets.Field | System.AttributeTargets.Parameter | System.AttributeTargets.Property, AllowMultiple=false)]
     public sealed partial class FileExtensionsAttribute : System.ComponentModel.DataAnnotations.DataTypeAttribute
@@ -155,19 +158,19 @@ namespace System.ComponentModel.DataAnnotations
         public FileExtensionsAttribute() : base (default(System.ComponentModel.DataAnnotations.DataType)) { }
         public string Extensions { get { throw null; } set { } }
         public override string FormatErrorMessage(string name) { throw null; }
-        public override bool IsValid(object value) { throw null; }
+        public override bool IsValid(object? value) { throw null; }
     }
     [System.AttributeUsageAttribute(System.AttributeTargets.Field | System.AttributeTargets.Property, AllowMultiple=false)]
     [System.ObsoleteAttribute("This attribute is no longer in use and will be ignored if applied.")]
     public sealed partial class FilterUIHintAttribute : System.Attribute
     {
         public FilterUIHintAttribute(string filterUIHint) { }
-        public FilterUIHintAttribute(string filterUIHint, string presentationLayer) { }
-        public FilterUIHintAttribute(string filterUIHint, string presentationLayer, params object[] controlParameters) { }
+        public FilterUIHintAttribute(string filterUIHint, string? presentationLayer) { }
+        public FilterUIHintAttribute(string filterUIHint, string? presentationLayer, params object[] controlParameters) { }
         public System.Collections.Generic.IDictionary<string, object> ControlParameters { get { throw null; } }
         public string FilterUIHint { get { throw null; } }
-        public string PresentationLayer { get { throw null; } }
-        public override bool Equals(object obj) { throw null; }
+        public string? PresentationLayer { get { throw null; } }
+        public override bool Equals(object? obj) { throw null; }
         public override int GetHashCode() { throw null; }
     }
     public partial interface IValidatableObject
@@ -186,7 +189,7 @@ namespace System.ComponentModel.DataAnnotations
         public MaxLengthAttribute(int length) { }
         public int Length { get { throw null; } }
         public override string FormatErrorMessage(string name) { throw null; }
-        public override bool IsValid(object value) { throw null; }
+        public override bool IsValid(object? value) { throw null; }
     }
     [System.AttributeUsageAttribute(System.AttributeTargets.Class, AllowMultiple=false)]
     public sealed partial class MetadataTypeAttribute : System.Attribute
@@ -200,13 +203,13 @@ namespace System.ComponentModel.DataAnnotations
         public MinLengthAttribute(int length) { }
         public int Length { get { throw null; } }
         public override string FormatErrorMessage(string name) { throw null; }
-        public override bool IsValid(object value) { throw null; }
+        public override bool IsValid(object? value) { throw null; }
     }
     [System.AttributeUsageAttribute(System.AttributeTargets.Field | System.AttributeTargets.Parameter | System.AttributeTargets.Property, AllowMultiple=false)]
     public sealed partial class PhoneAttribute : System.ComponentModel.DataAnnotations.DataTypeAttribute
     {
         public PhoneAttribute() : base (default(System.ComponentModel.DataAnnotations.DataType)) { }
-        public override bool IsValid(object value) { throw null; }
+        public override bool IsValid(object? value) { throw null; }
     }
     [System.AttributeUsageAttribute(System.AttributeTargets.Field | System.AttributeTargets.Parameter | System.AttributeTargets.Property, AllowMultiple=false)]
     public partial class RangeAttribute : System.ComponentModel.DataAnnotations.ValidationAttribute
@@ -220,7 +223,7 @@ namespace System.ComponentModel.DataAnnotations
         public System.Type OperandType { get { throw null; } }
         public bool ParseLimitsInInvariantCulture { get { throw null; } set { } }
         public override string FormatErrorMessage(string name) { throw null; }
-        public override bool IsValid(object value) { throw null; }
+        public override bool IsValid(object? value) { throw null; }
     }
     [System.AttributeUsageAttribute(System.AttributeTargets.Field | System.AttributeTargets.Parameter | System.AttributeTargets.Property, AllowMultiple=false)]
     public partial class RegularExpressionAttribute : System.ComponentModel.DataAnnotations.ValidationAttribute
@@ -229,14 +232,14 @@ namespace System.ComponentModel.DataAnnotations
         public int MatchTimeoutInMilliseconds { get { throw null; } set { } }
         public string Pattern { get { throw null; } }
         public override string FormatErrorMessage(string name) { throw null; }
-        public override bool IsValid(object value) { throw null; }
+        public override bool IsValid(object? value) { throw null; }
     }
     [System.AttributeUsageAttribute(System.AttributeTargets.Field | System.AttributeTargets.Parameter | System.AttributeTargets.Property, AllowMultiple=false)]
     public partial class RequiredAttribute : System.ComponentModel.DataAnnotations.ValidationAttribute
     {
         public RequiredAttribute() { }
         public bool AllowEmptyStrings { get { throw null; } set { } }
-        public override bool IsValid(object value) { throw null; }
+        public override bool IsValid(object? value) { throw null; }
     }
     [System.AttributeUsageAttribute(System.AttributeTargets.Field | System.AttributeTargets.Property, AllowMultiple=false)]
     public partial class ScaffoldColumnAttribute : System.Attribute
@@ -251,7 +254,7 @@ namespace System.ComponentModel.DataAnnotations
         public int MaximumLength { get { throw null; } }
         public int MinimumLength { get { throw null; } set { } }
         public override string FormatErrorMessage(string name) { throw null; }
-        public override bool IsValid(object value) { throw null; }
+        public override bool IsValid(object? value) { throw null; }
     }
     [System.AttributeUsageAttribute(System.AttributeTargets.Field | System.AttributeTargets.Property, AllowMultiple=false, Inherited=true)]
     public sealed partial class TimestampAttribute : System.Attribute
@@ -262,81 +265,81 @@ namespace System.ComponentModel.DataAnnotations
     public partial class UIHintAttribute : System.Attribute
     {
         public UIHintAttribute(string uiHint) { }
-        public UIHintAttribute(string uiHint, string presentationLayer) { }
-        public UIHintAttribute(string uiHint, string presentationLayer, params object[] controlParameters) { }
-        public System.Collections.Generic.IDictionary<string, object> ControlParameters { get { throw null; } }
-        public string PresentationLayer { get { throw null; } }
+        public UIHintAttribute(string uiHint, string? presentationLayer) { }
+        public UIHintAttribute(string uiHint, string? presentationLayer, params object?[]? controlParameters) { }
+        public System.Collections.Generic.IDictionary<string, object?> ControlParameters { get { throw null; } }
+        public string? PresentationLayer { get { throw null; } }
         public string UIHint { get { throw null; } }
-        public override bool Equals(object obj) { throw null; }
+        public override bool Equals(object? obj) { throw null; }
         public override int GetHashCode() { throw null; }
     }
     [System.AttributeUsageAttribute(System.AttributeTargets.Field | System.AttributeTargets.Parameter | System.AttributeTargets.Property, AllowMultiple=false)]
     public sealed partial class UrlAttribute : System.ComponentModel.DataAnnotations.DataTypeAttribute
     {
         public UrlAttribute() : base (default(System.ComponentModel.DataAnnotations.DataType)) { }
-        public override bool IsValid(object value) { throw null; }
+        public override bool IsValid(object? value) { throw null; }
     }
     public abstract partial class ValidationAttribute : System.Attribute
     {
         protected ValidationAttribute() { }
         protected ValidationAttribute(System.Func<string> errorMessageAccessor) { }
         protected ValidationAttribute(string errorMessage) { }
-        public string ErrorMessage { get { throw null; } set { } }
-        public string ErrorMessageResourceName { get { throw null; } set { } }
-        public System.Type ErrorMessageResourceType { get { throw null; } set { } }
+        public string? ErrorMessage { get { throw null; } set { } }
+        public string? ErrorMessageResourceName { get { throw null; } set { } }
+        public System.Type? ErrorMessageResourceType { get { throw null; } set { } }
         protected string ErrorMessageString { get { throw null; } }
         public virtual bool RequiresValidationContext { get { throw null; } }
         public virtual string FormatErrorMessage(string name) { throw null; }
-        public System.ComponentModel.DataAnnotations.ValidationResult GetValidationResult(object value, System.ComponentModel.DataAnnotations.ValidationContext validationContext) { throw null; }
-        public virtual bool IsValid(object value) { throw null; }
-        protected virtual System.ComponentModel.DataAnnotations.ValidationResult IsValid(object value, System.ComponentModel.DataAnnotations.ValidationContext validationContext) { throw null; }
-        public void Validate(object value, System.ComponentModel.DataAnnotations.ValidationContext validationContext) { }
-        public void Validate(object value, string name) { }
+        public System.ComponentModel.DataAnnotations.ValidationResult? GetValidationResult(object? value, System.ComponentModel.DataAnnotations.ValidationContext validationContext) { throw null; }
+        public virtual bool IsValid(object? value) { throw null; }
+        protected virtual System.ComponentModel.DataAnnotations.ValidationResult IsValid(object? value, System.ComponentModel.DataAnnotations.ValidationContext validationContext) { throw null; }
+        public void Validate(object? value, System.ComponentModel.DataAnnotations.ValidationContext validationContext) { }
+        public void Validate(object? value, string name) { }
     }
     public sealed partial class ValidationContext : System.IServiceProvider
     {
         public ValidationContext(object instance) { }
-        public ValidationContext(object instance, System.Collections.Generic.IDictionary<object, object> items) { }
-        public ValidationContext(object instance, System.IServiceProvider serviceProvider, System.Collections.Generic.IDictionary<object, object> items) { }
+        public ValidationContext(object instance, System.Collections.Generic.IDictionary<object, object>? items) { }
+        public ValidationContext(object instance, System.IServiceProvider? serviceProvider, System.Collections.Generic.IDictionary<object, object?>? items) { }
         public string DisplayName { get { throw null; } set { } }
-        public System.Collections.Generic.IDictionary<object, object> Items { get { throw null; } }
-        public string MemberName { get { throw null; } set { } }
+        public System.Collections.Generic.IDictionary<object, object?> Items { get { throw null; } }
+        public string? MemberName { get { throw null; } set { } }
         public object ObjectInstance { get { throw null; } }
         public System.Type ObjectType { get { throw null; } }
-        public object GetService(System.Type serviceType) { throw null; }
-        public void InitializeServiceProvider(System.Func<System.Type, object> serviceProvider) { }
+        public object? GetService(System.Type serviceType) { throw null; }
+        public void InitializeServiceProvider(System.Func<System.Type, object?> serviceProvider) { }
     }
     public partial class ValidationException : System.Exception
     {
         public ValidationException() { }
-        public ValidationException(System.ComponentModel.DataAnnotations.ValidationResult validationResult, System.ComponentModel.DataAnnotations.ValidationAttribute validatingAttribute, object value) { }
+        public ValidationException(System.ComponentModel.DataAnnotations.ValidationResult validationResult, System.ComponentModel.DataAnnotations.ValidationAttribute? validatingAttribute, object? value) { }
         protected ValidationException(System.Runtime.Serialization.SerializationInfo info, System.Runtime.Serialization.StreamingContext context) { }
-        public ValidationException(string message) { }
-        public ValidationException(string errorMessage, System.ComponentModel.DataAnnotations.ValidationAttribute validatingAttribute, object value) { }
-        public ValidationException(string message, System.Exception innerException) { }
-        public System.ComponentModel.DataAnnotations.ValidationAttribute ValidationAttribute { get { throw null; } }
+        public ValidationException(string? message) { }
+        public ValidationException(string? errorMessage, System.ComponentModel.DataAnnotations.ValidationAttribute? validatingAttribute, object? value) { }
+        public ValidationException(string? message, System.Exception? innerException) { }
+        public System.ComponentModel.DataAnnotations.ValidationAttribute? ValidationAttribute { get { throw null; } }
         public System.ComponentModel.DataAnnotations.ValidationResult ValidationResult { get { throw null; } }
-        public object Value { get { throw null; } }
+        public object? Value { get { throw null; } }
     }
     public partial class ValidationResult
     {
-        public static readonly System.ComponentModel.DataAnnotations.ValidationResult Success;
+        public static readonly System.ComponentModel.DataAnnotations.ValidationResult? Success;
         protected ValidationResult(System.ComponentModel.DataAnnotations.ValidationResult validationResult) { }
-        public ValidationResult(string errorMessage) { }
-        public ValidationResult(string errorMessage, System.Collections.Generic.IEnumerable<string> memberNames) { }
-        public string ErrorMessage { get { throw null; } set { } }
+        public ValidationResult(string? errorMessage) { }
+        public ValidationResult(string? errorMessage, System.Collections.Generic.IEnumerable<string>? memberNames) { }
+        public string? ErrorMessage { get { throw null; } set { } }
         public System.Collections.Generic.IEnumerable<string> MemberNames { get { throw null; } }
         public override string ToString() { throw null; }
     }
     public static partial class Validator
     {
-        public static bool TryValidateObject(object instance, System.ComponentModel.DataAnnotations.ValidationContext validationContext, System.Collections.Generic.ICollection<System.ComponentModel.DataAnnotations.ValidationResult> validationResults) { throw null; }
-        public static bool TryValidateObject(object instance, System.ComponentModel.DataAnnotations.ValidationContext validationContext, System.Collections.Generic.ICollection<System.ComponentModel.DataAnnotations.ValidationResult> validationResults, bool validateAllProperties) { throw null; }
-        public static bool TryValidateProperty(object value, System.ComponentModel.DataAnnotations.ValidationContext validationContext, System.Collections.Generic.ICollection<System.ComponentModel.DataAnnotations.ValidationResult> validationResults) { throw null; }
-        public static bool TryValidateValue(object value, System.ComponentModel.DataAnnotations.ValidationContext validationContext, System.Collections.Generic.ICollection<System.ComponentModel.DataAnnotations.ValidationResult> validationResults, System.Collections.Generic.IEnumerable<System.ComponentModel.DataAnnotations.ValidationAttribute> validationAttributes) { throw null; }
+        public static bool TryValidateObject(object instance, System.ComponentModel.DataAnnotations.ValidationContext validationContext, System.Collections.Generic.ICollection<System.ComponentModel.DataAnnotations.ValidationResult>? validationResults) { throw null; }
+        public static bool TryValidateObject(object instance, System.ComponentModel.DataAnnotations.ValidationContext validationContext, System.Collections.Generic.ICollection<System.ComponentModel.DataAnnotations.ValidationResult>? validationResults, bool validateAllProperties) { throw null; }
+        public static bool TryValidateProperty(object? value, System.ComponentModel.DataAnnotations.ValidationContext validationContext, System.Collections.Generic.ICollection<System.ComponentModel.DataAnnotations.ValidationResult>? validationResults) { throw null; }
+        public static bool TryValidateValue(object value, System.ComponentModel.DataAnnotations.ValidationContext validationContext, System.Collections.Generic.ICollection<System.ComponentModel.DataAnnotations.ValidationResult>? validationResults, System.Collections.Generic.IEnumerable<System.ComponentModel.DataAnnotations.ValidationAttribute> validationAttributes) { throw null; }
         public static void ValidateObject(object instance, System.ComponentModel.DataAnnotations.ValidationContext validationContext) { }
         public static void ValidateObject(object instance, System.ComponentModel.DataAnnotations.ValidationContext validationContext, bool validateAllProperties) { }
-        public static void ValidateProperty(object value, System.ComponentModel.DataAnnotations.ValidationContext validationContext) { }
+        public static void ValidateProperty(object? value, System.ComponentModel.DataAnnotations.ValidationContext validationContext) { }
         public static void ValidateValue(object value, System.ComponentModel.DataAnnotations.ValidationContext validationContext, System.Collections.Generic.IEnumerable<System.ComponentModel.DataAnnotations.ValidationAttribute> validationAttributes) { }
     }
 }
@@ -347,9 +350,10 @@ namespace System.ComponentModel.DataAnnotations.Schema
     {
         public ColumnAttribute() { }
         public ColumnAttribute(string name) { }
-        public string Name { get { throw null; } }
+        public string? Name { get { throw null; } }
         public int Order { get { throw null; } set { } }
-        public string TypeName { get { throw null; } set { } }
+        [System.Diagnostics.CodeAnalysis.DisallowNullAttribute]
+        public string? TypeName { get { throw null; } set { } }
     }
     [System.AttributeUsageAttribute(System.AttributeTargets.Class, AllowMultiple=false)]
     public partial class ComplexTypeAttribute : System.Attribute
@@ -390,6 +394,7 @@ namespace System.ComponentModel.DataAnnotations.Schema
     {
         public TableAttribute(string name) { }
         public string Name { get { throw null; } }
-        public string Schema { get { throw null; } set { } }
+        [System.Diagnostics.CodeAnalysis.DisallowNullAttribute]
+        public string? Schema { get { throw null; } set { } }
     }
 }
index 733060b..fdedddf 100644 (file)
@@ -1,6 +1,7 @@
 <Project Sdk="Microsoft.NET.Sdk">
   <PropertyGroup>
     <TargetFrameworks>netstandard2.1</TargetFrameworks>
+    <Nullable>enable</Nullable>
   </PropertyGroup>
   <ItemGroup>
     <Compile Include="System.ComponentModel.Annotations.cs" />
index e871a28..8e376bb 100644 (file)
@@ -1,6 +1,7 @@
 <Project Sdk="Microsoft.NET.Sdk">
   <PropertyGroup>
     <TargetFrameworks>netstandard2.1</TargetFrameworks>
+    <Nullable>enable</Nullable>
   </PropertyGroup>
   <ItemGroup>
     <Compile Include="System\ComponentModel\DataAnnotations\AssociatedMetadataTypeTypeDescriptor.cs" />
index b0ca160..fc7b7e4 100644 (file)
@@ -1,6 +1,9 @@
 // Licensed to the .NET Foundation under one or more agreements.
 // The .NET Foundation licenses this file to you under the MIT license.
 
+// TODO-NULLABLE: Enable after System.ComponentModel.TypeDescriptionProvider is annotated
+#nullable disable
+
 namespace System.ComponentModel.DataAnnotations
 {
     /// <summary>
index 7ce7d3a..2bc82d5 100644 (file)
@@ -1,6 +1,9 @@
 // Licensed to the .NET Foundation under one or more agreements.
 // The .NET Foundation licenses this file to you under the MIT license.
 
+// TODO-NULLABLE: Enable after System.ComponentModel.TypeDescriptionProvider is annotated
+#nullable disable
+
 using System.Collections.Concurrent;
 using System.Collections.Generic;
 using System.Globalization;
index 2276b3f..41078c0 100644 (file)
@@ -68,7 +68,7 @@ namespace System.ComponentModel.DataAnnotations
         /// </summary>
         /// <param name="key">The key to parse</param>
         /// <returns>Array of individual key members</returns>
-        private static string[] GetKeyMembers(string key)
+        private static string[] GetKeyMembers(string? key)
         {
             if (key == null)
             {
index 5b8ab82..dab56c6 100644 (file)
@@ -17,7 +17,7 @@ namespace System.ComponentModel.DataAnnotations
 
         public string OtherProperty { get; }
 
-        public string OtherPropertyDisplayName { get; internal set; }
+        public string? OtherPropertyDisplayName { get; internal set; }
 
         public override bool RequiresValidationContext => true;
 
@@ -25,7 +25,7 @@ namespace System.ComponentModel.DataAnnotations
             string.Format(
                 CultureInfo.CurrentCulture, ErrorMessageString, name, OtherPropertyDisplayName ?? OtherProperty);
 
-        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
+        protected override ValidationResult? IsValid(object? value, ValidationContext validationContext)
         {
             var otherPropertyInfo = validationContext.ObjectType.GetRuntimeProperty(OtherProperty);
             if (otherPropertyInfo == null)
@@ -37,7 +37,7 @@ namespace System.ComponentModel.DataAnnotations
                 throw new ArgumentException(SR.Format(SR.Common_PropertyNotFound, validationContext.ObjectType.FullName, OtherProperty));
             }
 
-            object otherPropertyValue = otherPropertyInfo.GetValue(validationContext.ObjectInstance, null);
+            object? otherPropertyValue = otherPropertyInfo.GetValue(validationContext.ObjectInstance, null);
             if (!Equals(value, otherPropertyValue))
             {
                 if (OtherPropertyDisplayName == null)
@@ -45,7 +45,7 @@ namespace System.ComponentModel.DataAnnotations
                     OtherPropertyDisplayName = GetDisplayNameForProperty(otherPropertyInfo);
                 }
 
-                string[] memberNames = validationContext.MemberName != null
+                string[]? memberNames = validationContext.MemberName != null
                    ? new[] { validationContext.MemberName }
                    : null;
                 return new ValidationResult(FormatErrorMessage(validationContext.DisplayName), memberNames);
@@ -54,12 +54,14 @@ namespace System.ComponentModel.DataAnnotations
             return null;
         }
 
-        private string GetDisplayNameForProperty(PropertyInfo property)
+        private string? GetDisplayNameForProperty(PropertyInfo property)
         {
             var attributes = CustomAttributeExtensions.GetCustomAttributes(property, true);
             var display = attributes.OfType<DisplayAttribute>().FirstOrDefault();
             if (display != null)
             {
+                // TODO-NULLABLE: This will return null if [DisplayName] is specified but no Name has been defined - probably a bug.
+                // Should fall back to OtherProperty in this case instead.
                 return display.GetName();
             }
 
index a9a5aea..4715007 100644 (file)
@@ -15,7 +15,7 @@ namespace System.ComponentModel.DataAnnotations
             DefaultErrorMessage = SR.CreditCardAttribute_Invalid;
         }
 
-        public override bool IsValid(object value)
+        public override bool IsValid(object? value)
         {
             if (value == null)
             {
index 58b8a01..67c7077 100644 (file)
@@ -58,12 +58,12 @@ namespace System.ComponentModel.DataAnnotations
     {
         #region Member Fields
 
-        private readonly Lazy<string> _malformedErrorMessage;
+        private readonly Lazy<string?> _malformedErrorMessage;
         private bool _isSingleArgumentMethod;
-        private string _lastMessage;
-        private MethodInfo _methodInfo;
-        private Type _firstParameterType;
-        private Tuple<string, Type> _typeId;
+        private string? _lastMessage;
+        private MethodInfo? _methodInfo;
+        private Type? _firstParameterType;
+        private Tuple<string, Type>? _typeId;
 
         #endregion
 
@@ -88,7 +88,7 @@ namespace System.ComponentModel.DataAnnotations
         {
             ValidatorType = validatorType;
             Method = method;
-            _malformedErrorMessage = new Lazy<string>(CheckAttributeWellFormed);
+            _malformedErrorMessage = new Lazy<string?>(CheckAttributeWellFormed);
         }
 
         #endregion
@@ -143,7 +143,7 @@ namespace System.ComponentModel.DataAnnotations
         /// </param>
         /// <returns>Whatever the <see cref="Method" /> in <see cref="ValidatorType" /> returns.</returns>
         /// <exception cref="InvalidOperationException"> is thrown if the current attribute is malformed.</exception>
-        protected override ValidationResult IsValid(object value, ValidationContext validationContext)
+        protected override ValidationResult? IsValid(object? value, ValidationContext validationContext)
         {
             // If attribute is not valid, throw an exception right away to inform the developer
             ThrowIfAttributeNotWellFormed();
@@ -153,7 +153,7 @@ namespace System.ComponentModel.DataAnnotations
             // If the value is not of the correct type and cannot be converted, fail
             // to indicate it is not acceptable.  The convention is that IsValid is merely a probe,
             // and clients are not expecting exceptions.
-            object convertedValue;
+            object? convertedValue;
             if (!TryConvertValue(value, out convertedValue))
             {
                 return new ValidationResult(SR.Format(SR.CustomValidationAttribute_Type_Conversion_Failed,
@@ -171,10 +171,10 @@ namespace System.ComponentModel.DataAnnotations
                 // 1-parameter form is ValidationResult Method(object value)
                 // 2-parameter form is ValidationResult Method(object value, ValidationContext context),
                 var methodParams = _isSingleArgumentMethod
-                    ? new object[] { convertedValue }
+                    ? new object?[] { convertedValue }
                     : new[] { convertedValue, validationContext };
 
-                var result = (ValidationResult)methodInfo.Invoke(null, methodParams);
+                var result = (ValidationResult?)methodInfo!.Invoke(null, methodParams);
 
                 // We capture the message they provide us only in the event of failure,
                 // otherwise we use the normal message supplied via the ctor
@@ -189,7 +189,7 @@ namespace System.ComponentModel.DataAnnotations
             }
             catch (TargetInvocationException tie)
             {
-                throw tie.InnerException;
+                throw tie.InnerException!;
             }
         }
 
@@ -217,13 +217,13 @@ namespace System.ComponentModel.DataAnnotations
         ///     Checks whether the current attribute instance itself is valid for use.
         /// </summary>
         /// <returns>The error message why it is not well-formed, null if it is well-formed.</returns>
-        private string CheckAttributeWellFormed() => ValidateValidatorTypeParameter() ?? ValidateMethodParameter();
+        private string? CheckAttributeWellFormed() => ValidateValidatorTypeParameter() ?? ValidateMethodParameter();
 
         /// <summary>
         ///     Internal helper to determine whether <see cref="ValidatorType" /> is legal for use.
         /// </summary>
         /// <returns><c>null</c> or the appropriate error message.</returns>
-        private string ValidateValidatorTypeParameter()
+        private string? ValidateValidatorTypeParameter()
         {
             if (ValidatorType == null)
             {
@@ -242,7 +242,7 @@ namespace System.ComponentModel.DataAnnotations
         ///     Internal helper to determine whether <see cref="Method" /> is legal for use.
         /// </summary>
         /// <returns><c>null</c> or the appropriate error message.</returns>
-        private string ValidateMethodParameter()
+        private string? ValidateMethodParameter()
         {
             if (string.IsNullOrEmpty(Method))
             {
@@ -295,7 +295,7 @@ namespace System.ComponentModel.DataAnnotations
         /// </summary>
         private void ThrowIfAttributeNotWellFormed()
         {
-            string errorMessage = _malformedErrorMessage.Value;
+            string? errorMessage = _malformedErrorMessage.Value;
             if (errorMessage != null)
             {
                 throw new InvalidOperationException(errorMessage);
@@ -309,10 +309,10 @@ namespace System.ComponentModel.DataAnnotations
         /// <param name="value">The value to check/convert.</param>
         /// <param name="convertedValue">If successful, the converted (or copied) value.</param>
         /// <returns><c>true</c> if type value was already correct or was successfully converted.</returns>
-        private bool TryConvertValue(object value, out object convertedValue)
+        private bool TryConvertValue(object? value, out object? convertedValue)
         {
             convertedValue = null;
-            var expectedValueType = _firstParameterType;
+            var expectedValueType = _firstParameterType!;
 
             // Null is permitted for reference types or for Nullable<>'s only
             if (value == null)
index 443b3b7..d6ea70b 100644 (file)
@@ -67,12 +67,12 @@ namespace System.ComponentModel.DataAnnotations
         ///     Gets the string representing a custom data type. Returns a non-null value only if <see cref="DataType" /> is
         ///     DataType.Custom.
         /// </summary>
-        public string CustomDataType { get; }
+        public string? CustomDataType { get; }
 
         /// <summary>
         ///     Gets the default display format that gets used along with this DataType.
         /// </summary>
-        public DisplayFormatAttribute DisplayFormat { get; protected set; }
+        public DisplayFormatAttribute? DisplayFormat { get; protected set; }
 
         /// <summary>
         ///     Return the name of the data type, either using the <see cref="DataType" /> enum or <see cref="CustomDataType" />
@@ -87,7 +87,7 @@ namespace System.ComponentModel.DataAnnotations
             if (DataType == DataType.Custom)
             {
                 // If it's a custom type string, use it as the template name
-                return CustomDataType;
+                return CustomDataType!;
             }
             // If it's an enum, turn it into a string
             // Use the cached array with enum string values instead of ToString() as the latter is too slow
@@ -101,7 +101,7 @@ namespace System.ComponentModel.DataAnnotations
         /// <param name="value">The value to validate</param>
         /// <returns>Unconditionally returns <c>true</c></returns>
         /// <exception cref="InvalidOperationException"> is thrown if the current attribute is ill-formed.</exception>
-        public override bool IsValid(object value)
+        public override bool IsValid(object? value)
         {
             EnsureValidDataType();
 
index 0b6d9a9..2d8b11f 100644 (file)
@@ -25,7 +25,7 @@ namespace System.ComponentModel.DataAnnotations
         private bool? _autoGenerateField;
         private bool? _autoGenerateFilter;
         private int? _order;
-        private Type _resourceType;
+        private Type? _resourceType;
 
         #endregion
 
@@ -54,7 +54,7 @@ namespace System.ComponentModel.DataAnnotations
         ///     The short name is generally used as the grid column label for a UI element bound to the member
         ///     bearing this attribute.  A <c>null</c> or empty string is legal, and consumers must allow for that.
         /// </value>
-        public string ShortName
+        public string? ShortName
         {
             get => _shortName.Value;
             set => _shortName.Value = value;
@@ -79,7 +79,7 @@ namespace System.ComponentModel.DataAnnotations
         ///     The name is generally used as the field label for a UI element bound to the member
         ///     bearing this attribute.  A <c>null</c> or empty string is legal, and consumers must allow for that.
         /// </value>
-        public string Name
+        public string? Name
         {
             get => _name.Value;
             set => _name.Value = value;
@@ -104,7 +104,7 @@ namespace System.ComponentModel.DataAnnotations
         ///     Description is generally used as a tool tip or description a UI element bound to the member
         ///     bearing this attribute.  A <c>null</c> or empty string is legal, and consumers must allow for that.
         /// </value>
-        public string Description
+        public string? Description
         {
             get => _description.Value;
             set => _description.Value = value;
@@ -129,7 +129,7 @@ namespace System.ComponentModel.DataAnnotations
         ///     A prompt is generally used as a prompt or watermark for a UI element bound to the member
         ///     bearing this attribute.  A <c>null</c> or empty string is legal, and consumers must allow for that.
         /// </value>
-        public string Prompt
+        public string? Prompt
         {
             get => _prompt.Value;
             set => _prompt.Value = value;
@@ -154,7 +154,7 @@ namespace System.ComponentModel.DataAnnotations
         ///     A group name is used for grouping fields into the UI.  A <c>null</c> or empty string is legal,
         ///     and consumers must allow for that.
         /// </value>
-        public string GroupName
+        public string? GroupName
         {
             get => _groupName.Value;
             set => _groupName.Value = value;
@@ -167,7 +167,7 @@ namespace System.ComponentModel.DataAnnotations
         ///     <see cref="GetName" />, <see cref="GetDescription" />, <see cref="GetPrompt" />, and <see cref="GetGroupName" />
         ///     methods to return localized values.
         /// </summary>
-        public Type ResourceType
+        public Type? ResourceType
         {
             get => _resourceType;
             set
@@ -298,7 +298,7 @@ namespace System.ComponentModel.DataAnnotations
         ///     but a public static property with a name matching the <see cref="ShortName" /> value couldn't be found
         ///     on the <see cref="ResourceType" />.
         /// </exception>
-        public string GetShortName() => _shortName.GetLocalizableValue() ?? GetName();
+        public string? GetShortName() => _shortName.GetLocalizableValue() ?? GetName();
 
         /// <summary>
         ///     Gets the UI display string for Name.
@@ -325,7 +325,7 @@ namespace System.ComponentModel.DataAnnotations
         ///     but a public static property with a name matching the <see cref="Name" /> value couldn't be found
         ///     on the <see cref="ResourceType" />.
         /// </exception>
-        public string GetName() => _name.GetLocalizableValue();
+        public string? GetName() => _name.GetLocalizableValue();
 
         /// <summary>
         ///     Gets the UI display string for Description.
@@ -348,7 +348,7 @@ namespace System.ComponentModel.DataAnnotations
         ///     but a public static property with a name matching the <see cref="Description" /> value couldn't be found
         ///     on the <see cref="ResourceType" />.
         /// </exception>
-        public string GetDescription() => _description.GetLocalizableValue();
+        public string? GetDescription() => _description.GetLocalizableValue();
 
         /// <summary>
         ///     Gets the UI display string for Prompt.
@@ -371,7 +371,7 @@ namespace System.ComponentModel.DataAnnotations
         ///     but a public static property with a name matching the <see cref="Prompt" /> value couldn't be found
         ///     on the <see cref="ResourceType" />.
         /// </exception>
-        public string GetPrompt() => _prompt.GetLocalizableValue();
+        public string? GetPrompt() => _prompt.GetLocalizableValue();
 
         /// <summary>
         ///     Gets the UI display string for GroupName.
@@ -394,7 +394,7 @@ namespace System.ComponentModel.DataAnnotations
         ///     but a public static property with a name matching the <see cref="GroupName" /> value couldn't be found
         ///     on the <see cref="ResourceType" />.
         /// </exception>
-        public string GetGroupName() => _groupName.GetLocalizableValue();
+        public string? GetGroupName() => _groupName.GetLocalizableValue();
 
         /// <summary>
         ///     Gets the value of <see cref="AutoGenerateField" /> if it has been set, or <c>null</c>.
index 1ed02df..d13f5cd 100644 (file)
@@ -15,12 +15,12 @@ namespace System.ComponentModel.DataAnnotations
         {
         }
 
-        public DisplayColumnAttribute(string displayColumn, string sortColumn)
+        public DisplayColumnAttribute(string displayColumn, string? sortColumn)
             : this(displayColumn, sortColumn, false)
         {
         }
 
-        public DisplayColumnAttribute(string displayColumn, string sortColumn, bool sortDescending)
+        public DisplayColumnAttribute(string displayColumn, string? sortColumn, bool sortDescending)
         {
             DisplayColumn = displayColumn;
             SortColumn = sortColumn;
@@ -29,7 +29,7 @@ namespace System.ComponentModel.DataAnnotations
 
         public string DisplayColumn { get; }
 
-        public string SortColumn { get; }
+        public string? SortColumn { get; }
 
         public bool SortDescending { get; }
     }
index 76b7a8b..96a82b0 100644 (file)
@@ -25,7 +25,7 @@ namespace System.ComponentModel.DataAnnotations
         /// <summary>
         ///     Gets or sets the format string
         /// </summary>
-        public string DataFormatString { get; set; }
+        public string? DataFormatString { get; set; }
 
         /// <summary>
         ///     Gets or sets the string to display when the value is null, which may be a resource key string.
@@ -46,7 +46,7 @@ namespace System.ComponentModel.DataAnnotations
         ///     The null display text is generally used as placeholder when the value is not specified.
         ///     A <c>null</c> or empty string is legal, and consumers must allow for that.
         /// </value>
-        public string NullDisplayText
+        public string? NullDisplayText
         {
             get => _nullDisplayText.Value;
             set => _nullDisplayText.Value = value;
@@ -72,7 +72,7 @@ namespace System.ComponentModel.DataAnnotations
         ///     Using <see cref="NullDisplayTextResourceType" /> along with <see cref="NullDisplayText" />, allows the <see cref="GetNullDisplayText" />
         ///     method to return localized values.
         /// </summary>
-        public Type NullDisplayTextResourceType
+        public Type? NullDisplayTextResourceType
         {
             get => _nullDisplayText.ResourceType;
             set => _nullDisplayText.ResourceType = value;
@@ -102,6 +102,6 @@ namespace System.ComponentModel.DataAnnotations
         ///     but a public static property with a name matching the <see cref="NullDisplayText" /> value couldn't be found
         ///     on the <see cref="NullDisplayTextResourceType" />.
         /// </exception>
-        public string GetNullDisplayText() => _nullDisplayText.GetLocalizableValue();
+        public string? GetNullDisplayText() => _nullDisplayText.GetLocalizableValue();
     }
 }
index eba694c..2e28b0c 100644 (file)
@@ -15,7 +15,7 @@ namespace System.ComponentModel.DataAnnotations
             DefaultErrorMessage = SR.EmailAddressAttribute_Invalid;
         }
 
-        public override bool IsValid(object value)
+        public override bool IsValid(object? value)
         {
             if (value == null)
             {
index ba0a48e..18dd723 100644 (file)
@@ -20,7 +20,7 @@ namespace System.ComponentModel.DataAnnotations
 
         public Type EnumType { get; }
 
-        public override bool IsValid(object value)
+        public override bool IsValid(object? value)
         {
             if (EnumType == null)
             {
@@ -91,8 +91,8 @@ namespace System.ComponentModel.DataAnnotations
                 // If it is, the string representation of the enum value will be something like "A, B", while
                 // the string representation of the underlying value will be "3". If the enum value does not
                 // match a valid flag combination, then it would also be something like "3".
-                string underlying = GetUnderlyingTypeValueString(EnumType, convertedValue);
-                string converted = convertedValue.ToString();
+                string underlying = GetUnderlyingTypeValueString(EnumType, convertedValue)!;
+                string? converted = convertedValue.ToString();
                 return !underlying.Equals(converted);
             }
 
@@ -102,7 +102,7 @@ namespace System.ComponentModel.DataAnnotations
         private static bool IsEnumTypeInFlagsMode(Type enumType) =>
             enumType.GetCustomAttributes(typeof(FlagsAttribute), false).Any();
 
-        private static string GetUnderlyingTypeValueString(Type enumType, object enumValue) =>
+        private static string? GetUnderlyingTypeValueString(Type enumType, object enumValue) =>
             Convert.ChangeType(enumValue, Enum.GetUnderlyingType(enumType), CultureInfo.InvariantCulture).ToString();
     }
 }
index df2f1fc..e66e280 100644 (file)
@@ -12,7 +12,7 @@ namespace System.ComponentModel.DataAnnotations
         AllowMultiple = false)]
     public sealed class FileExtensionsAttribute : DataTypeAttribute
     {
-        private string _extensions;
+        private string? _extensions;
 
         public FileExtensionsAttribute()
             : base(DataType.Upload)
@@ -42,7 +42,7 @@ namespace System.ComponentModel.DataAnnotations
         public override string FormatErrorMessage(string name) =>
             string.Format(CultureInfo.CurrentCulture, ErrorMessageString, name, ExtensionsFormatted);
 
-        public override bool IsValid(object value) =>
+        public override bool IsValid(object? value) =>
             value == null || value is string valueAsString && ValidateExtension(valueAsString);
 
         private bool ValidateExtension(string fileName)
index e30b283..bb5138e 100644 (file)
@@ -24,14 +24,14 @@ namespace System.ComponentModel.DataAnnotations
         /// Gets the name of the presentation layer that supports the control type
         /// in <see cref="FilterUIHint"/>
         /// </summary>
-        public string PresentationLayer => _implementation.PresentationLayer;
+        public string? PresentationLayer => _implementation.PresentationLayer;
 
         /// <summary>
         /// Gets the name-value pairs used as parameters to the control's constructor
         /// </summary>
         /// <exception cref="InvalidOperationException"> is thrown if the current attribute
         /// is ill-formed.</exception>
-        public IDictionary<string, object> ControlParameters => _implementation.ControlParameters;
+        public IDictionary<string, object?> ControlParameters => _implementation.ControlParameters;
 
         /// <summary>
         /// Constructor that accepts the name of the control, without specifying
@@ -50,7 +50,7 @@ namespace System.ComponentModel.DataAnnotations
         /// <param name="filterUIHint">The name of the control to use</param>
         /// <param name="presentationLayer">The name of the presentation layer that
         /// supports this control</param>
-        public FilterUIHintAttribute(string filterUIHint, string presentationLayer)
+        public FilterUIHintAttribute(string filterUIHint, string? presentationLayer)
             : this(filterUIHint, presentationLayer, Array.Empty<object>())
         {
         }
@@ -62,8 +62,8 @@ namespace System.ComponentModel.DataAnnotations
         /// <param name="filterUIHint">The name of the control</param>
         /// <param name="presentationLayer">The presentation layer</param>
         /// <param name="controlParameters">The list of parameters for the control</param>
-        public FilterUIHintAttribute(string filterUIHint, string presentationLayer,
-            params object[] controlParameters)
+        public FilterUIHintAttribute(string filterUIHint, string? presentationLayer,
+            params object?[] controlParameters)
         {
             _implementation = new UIHintAttribute.UIHintImplementation(
                 filterUIHint, presentationLayer, controlParameters);
@@ -82,7 +82,7 @@ namespace System.ComponentModel.DataAnnotations
         /// <param name="obj">An System.Object.</param>
         /// <returns>true if obj is a FilterUIHintAttribute and its value is the same
         /// as this instance; otherwise, false.</returns>
-        public override bool Equals(object obj) =>
+        public override bool Equals(object? obj) =>
             obj is FilterUIHintAttribute otherAttribute && _implementation.Equals(otherAttribute._implementation);
     }
 }
index a65becd..5c8dfca 100644 (file)
@@ -15,9 +15,9 @@ namespace System.ComponentModel.DataAnnotations
         #region Member fields
 
         private readonly string _propertyName;
-        private Func<string> _cachedResult;
-        private string _propertyValue;
-        private Type _resourceType;
+        private Func<string?>? _cachedResult;
+        private string? _propertyValue;
+        private Type? _resourceType;
 
         #endregion
 
@@ -46,7 +46,7 @@ namespace System.ComponentModel.DataAnnotations
         ///     either the literal, non-localized value, or it can be a resource name
         ///     found on the resource type supplied to <see cref="GetLocalizableValue" />.
         /// </summary>
-        public string Value
+        public string? Value
         {
             get => _propertyValue;
             set
@@ -62,7 +62,7 @@ namespace System.ComponentModel.DataAnnotations
         /// <summary>
         ///     Gets or sets the resource type to be used for localization.
         /// </summary>
-        public Type ResourceType
+        public Type? ResourceType
         {
             get => _resourceType;
             set
@@ -108,7 +108,7 @@ namespace System.ComponentModel.DataAnnotations
         /// <returns>
         ///     Returns the potentially localized value.
         /// </returns>
-        public string GetLocalizableValue()
+        public string? GetLocalizableValue()
         {
             if (_cachedResult == null)
             {
@@ -153,7 +153,7 @@ namespace System.ComponentModel.DataAnnotations
                     else
                     {
                         // We have a valid property, so cache the resource
-                        _cachedResult = () => (string)property.GetValue(null, null);
+                        _cachedResult = () => (string?)property!.GetValue(null, null);
                     }
                 }
             }
index 76d2e74..903112d 100644 (file)
@@ -59,7 +59,7 @@ namespace System.ComponentModel.DataAnnotations
         ///     <c>true</c> if the value is null or less than or equal to the specified maximum length, otherwise <c>false</c>
         /// </returns>
         /// <exception cref="InvalidOperationException">Length is zero or less than negative one.</exception>
-        public override bool IsValid(object value)
+        public override bool IsValid(object? value)
         {
             // Check the lengths for legality
             EnsureLegalLengths();
@@ -120,10 +120,10 @@ namespace System.ComponentModel.DataAnnotations
                 return true;
             }
 
-            PropertyInfo property = value.GetType().GetRuntimeProperty("Count");
+            PropertyInfo? property = value.GetType().GetRuntimeProperty("Count");
             if (property != null && property.CanRead && property.PropertyType == typeof(int))
             {
-                count = (int)property.GetValue(value);
+                count = (int)property.GetValue(value)!;
                 return true;
             }
 
index 0b34a5f..7b0e09f 100644 (file)
@@ -43,7 +43,7 @@ namespace System.ComponentModel.DataAnnotations
         ///     <c>false</c>
         /// </returns>
         /// <exception cref="InvalidOperationException">Length is less than zero.</exception>
-        public override bool IsValid(object value)
+        public override bool IsValid(object? value)
         {
             // Check the lengths for legality
             EnsureLegalLengths();
index d264e5e..cec872c 100644 (file)
@@ -20,7 +20,7 @@ namespace System.ComponentModel.DataAnnotations
             DefaultErrorMessage = SR.PhoneAttribute_Invalid;
         }
 
-        public override bool IsValid(object value)
+        public override bool IsValid(object? value)
         {
             if (value == null)
             {
index 3e9bb75..a3b2e0b 100644 (file)
@@ -84,9 +84,9 @@ namespace System.ComponentModel.DataAnnotations
         /// parameters, for which the invariant culture is always used for any conversions of the validated value.</remarks>
         public bool ConvertValueInInvariantCulture { get; set; }
 
-        private Func<object, object> Conversion { get; set; }
+        private Func<object, object?>? Conversion { get; set; }
 
-        private void Initialize(IComparable minimum, IComparable maximum, Func<object, object> conversion)
+        private void Initialize(IComparable minimum, IComparable maximum, Func<object, object?> conversion)
         {
             if (minimum.CompareTo(maximum) > 0)
             {
@@ -104,7 +104,7 @@ namespace System.ComponentModel.DataAnnotations
         /// <param name="value">The value to test for validity.</param>
         /// <returns><c>true</c> means the <paramref name="value" /> is valid</returns>
         /// <exception cref="InvalidOperationException"> is thrown if the current attribute is ill-formed.</exception>
-        public override bool IsValid(object value)
+        public override bool IsValid(object? value)
         {
             // Validate our properties and create the conversion function
             SetupConversion();
@@ -115,11 +115,11 @@ namespace System.ComponentModel.DataAnnotations
                 return true;
             }
 
-            object convertedValue;
+            object? convertedValue;
 
             try
             {
-                convertedValue = Conversion(value);
+                convertedValue = Conversion!(value);
             }
             catch (FormatException)
             {
@@ -207,7 +207,7 @@ namespace System.ComponentModel.DataAnnotations
                         ? converter.ConvertFromInvariantString((string)maximum)
                         : converter.ConvertFromString((string)maximum));
 
-                    Func<object, object> conversion;
+                    Func<object, object?> conversion;
                     if (ConvertValueInInvariantCulture)
                     {
                         conversion = value => value.GetType() == type
index 79c1a7a..e7f4eb1 100644 (file)
@@ -35,7 +35,7 @@ namespace System.ComponentModel.DataAnnotations
         /// </summary>
         public string Pattern { get; }
 
-        private Regex Regex { get; set; }
+        private Regex? Regex { get; set; }
 
         /// <summary>
         ///     Override of <see cref="ValidationAttribute.IsValid(object)" />
@@ -47,12 +47,12 @@ namespace System.ComponentModel.DataAnnotations
         /// <returns><c>true</c> if the given value matches the current regular expression pattern</returns>
         /// <exception cref="InvalidOperationException"> is thrown if the current attribute is ill-formed.</exception>
         /// <exception cref="ArgumentException"> is thrown if the <see cref="Pattern" /> is not a valid regular expression.</exception>
-        public override bool IsValid(object value)
+        public override bool IsValid(object? value)
         {
             SetupRegex();
 
             // Convert the value to a string
-            string stringValue = Convert.ToString(value, CultureInfo.CurrentCulture);
+            string? stringValue = Convert.ToString(value, CultureInfo.CurrentCulture);
 
             // Automatically pass if value is null or empty. RequiredAttribute should be used to assert a value is not empty.
             if (string.IsNullOrEmpty(stringValue))
@@ -60,7 +60,7 @@ namespace System.ComponentModel.DataAnnotations
                 return true;
             }
 
-            var m = Regex.Match(stringValue);
+            var m = Regex!.Match(stringValue);
 
             // We are looking for an exact match, not just a search hit. This matches what
             // the RegularExpressionValidator control does
index f723349..a5003f0 100644 (file)
@@ -36,7 +36,7 @@ namespace System.ComponentModel.DataAnnotations
         ///     <see cref="RequiredAttribute.AllowEmptyStrings" />
         ///     then <c>false</c> is returned only if <paramref name="value" /> is null.
         /// </returns>
-        public override bool IsValid(object value)
+        public override bool IsValid(object? value)
         {
             if (value == null)
             {
index d1e5583..f871d3d 100644 (file)
@@ -1,6 +1,7 @@
 // Licensed to the .NET Foundation under one or more agreements.
 // The .NET Foundation licenses this file to you under the MIT license.
 
+using System.Diagnostics.CodeAnalysis;
 using System.Globalization;
 
 namespace System.ComponentModel.DataAnnotations.Schema
@@ -12,7 +13,7 @@ namespace System.ComponentModel.DataAnnotations.Schema
     public class ColumnAttribute : Attribute
     {
         private int _order = -1;
-        private string _typeName;
+        private string? _typeName;
 
         /// <summary>
         ///     Initializes a new instance of the <see cref="ColumnAttribute" /> class.
@@ -38,7 +39,7 @@ namespace System.ComponentModel.DataAnnotations.Schema
         /// <summary>
         ///     The name of the column the property is mapped to.
         /// </summary>
-        public string Name { get; }
+        public string? Name { get; }
 
         /// <summary>
         ///     The zero-based order of the column the property is mapped to.
@@ -60,7 +61,8 @@ namespace System.ComponentModel.DataAnnotations.Schema
         /// <summary>
         ///     The database provider specific data type of the column the property is mapped to.
         /// </summary>
-        public string TypeName
+        [DisallowNull]
+        public string? TypeName
         {
             get => _typeName;
             set
index 9111614..489bf85 100644 (file)
@@ -1,6 +1,7 @@
 // Licensed to the .NET Foundation under one or more agreements.
 // The .NET Foundation licenses this file to you under the MIT license.
 
+using System.Diagnostics.CodeAnalysis;
 using System.Globalization;
 
 namespace System.ComponentModel.DataAnnotations.Schema
@@ -11,7 +12,7 @@ namespace System.ComponentModel.DataAnnotations.Schema
     [AttributeUsage(AttributeTargets.Class, AllowMultiple = false)]
     public class TableAttribute : Attribute
     {
-        private string _schema;
+        private string? _schema;
 
         /// <summary>
         ///     Initializes a new instance of the <see cref="TableAttribute" /> class.
@@ -35,7 +36,8 @@ namespace System.ComponentModel.DataAnnotations.Schema
         /// <summary>
         ///     The schema of the table the class is mapped to.
         /// </summary>
-        public string Schema
+        [DisallowNull]
+        public string? Schema
         {
             get => _schema;
             set
index f6cb119..17e39ee 100644 (file)
@@ -42,7 +42,7 @@ namespace System.ComponentModel.DataAnnotations
         /// <param name="value">The value to test.</param>
         /// <returns><c>true</c> if the value is null or less than or equal to the set maximum length</returns>
         /// <exception cref="InvalidOperationException"> is thrown if the current attribute is ill-formed.</exception>
-        public override bool IsValid(object value)
+        public override bool IsValid(object? value)
         {
             // Check the lengths for legality
             EnsureLegalLengths();
index 21de33d..f92ebaa 100644 (file)
@@ -42,7 +42,7 @@ namespace System.ComponentModel.DataAnnotations
         /// <param name="uiHint">The name of the control</param>
         /// <param name="presentationLayer">The presentation layer</param>
         /// <param name="controlParameters">The list of parameters for the control</param>
-        public UIHintAttribute(string uiHint, string presentationLayer, params object[] controlParameters)
+        public UIHintAttribute(string uiHint, string? presentationLayer, params object?[]? controlParameters)
         {
             _implementation = new UIHintImplementation(uiHint, presentationLayer, controlParameters);
         }
@@ -55,25 +55,25 @@ namespace System.ComponentModel.DataAnnotations
         /// <summary>
         ///     Gets the name of the presentation layer that supports the control type in <see cref="UIHint" />
         /// </summary>
-        public string PresentationLayer => _implementation.PresentationLayer;
+        public string? PresentationLayer => _implementation.PresentationLayer;
 
         /// <summary>
         ///     Gets the name-value pairs used as parameters to the control's constructor
         /// </summary>
         /// <exception cref="InvalidOperationException"> is thrown if the current attribute is ill-formed.</exception>
-        public IDictionary<string, object> ControlParameters => _implementation.ControlParameters;
+        public IDictionary<string, object?> ControlParameters => _implementation.ControlParameters;
 
         public override int GetHashCode() => _implementation.GetHashCode();
 
-        public override bool Equals(object obj) =>
+        public override bool Equals(object? obj) =>
             obj is UIHintAttribute otherAttribute && _implementation.Equals(otherAttribute._implementation);
 
         internal class UIHintImplementation
         {
-            private readonly object[] _inputControlParameters;
-            private IDictionary<string, object> _controlParameters;
+            private readonly object?[]? _inputControlParameters;
+            private IDictionary<string, object?>? _controlParameters;
 
-            public UIHintImplementation(string uiHint, string presentationLayer, params object[] controlParameters)
+            public UIHintImplementation(string uiHint, string? presentationLayer, params object?[]? controlParameters)
             {
                 UIHint = uiHint;
                 PresentationLayer = presentationLayer;
@@ -92,12 +92,12 @@ namespace System.ComponentModel.DataAnnotations
             /// <summary>
             ///     Gets the name of the presentation layer that supports the control type in <see cref="UIHint" />
             /// </summary>
-            public string PresentationLayer { get; }
+            public string? PresentationLayer { get; }
 
             // Lazy load the dictionary. It's fine if this method executes multiple times in stress scenarios.
             // If the method throws (indicating that the input params are invalid) this property will throw
             // every time it's accessed.
-            public IDictionary<string, object> ControlParameters =>
+            public IDictionary<string, object?> ControlParameters =>
                 _controlParameters ?? (_controlParameters = BuildControlParametersDictionary());
 
             /// <summary>
@@ -118,18 +118,19 @@ namespace System.ComponentModel.DataAnnotations
             /// </summary>
             /// <param name="obj">An System.Object.</param>
             /// <returns>true if obj is a UIHintAttribute and its value is the same as this instance; otherwise, false.</returns>
-            public override bool Equals(object obj)
+            public override bool Equals(object? obj)
             {
-                // don't need to perform a type check on obj since this is an internal class
-                var otherImplementation = (UIHintImplementation)obj;
+                var otherImplementation = obj as UIHintImplementation;
 
-                if (UIHint != otherImplementation.UIHint || PresentationLayer != otherImplementation.PresentationLayer)
+                if (otherImplementation is null ||
+                    UIHint != otherImplementation.UIHint ||
+                    PresentationLayer != otherImplementation.PresentationLayer)
                 {
                     return false;
                 }
 
-                IDictionary<string, object> leftParams;
-                IDictionary<string, object> rightParams;
+                IDictionary<string, object?> leftParams;
+                IDictionary<string, object?> rightParams;
 
                 try
                 {
@@ -157,11 +158,11 @@ namespace System.ComponentModel.DataAnnotations
             /// <returns>
             ///     Dictionary of control parameters.
             /// </returns>
-            private IDictionary<string, object> BuildControlParametersDictionary()
+            private IDictionary<string, object?> BuildControlParametersDictionary()
             {
-                IDictionary<string, object> controlParameters = new Dictionary<string, object>();
+                IDictionary<string, object?> controlParameters = new Dictionary<string, object?>();
 
-                object[] inputControlParameters = _inputControlParameters;
+                object?[]? inputControlParameters = _inputControlParameters;
 
                 if (inputControlParameters == null || inputControlParameters.Length == 0)
                 {
@@ -174,8 +175,8 @@ namespace System.ComponentModel.DataAnnotations
 
                 for (int i = 0; i < inputControlParameters.Length; i += 2)
                 {
-                    object key = inputControlParameters[i];
-                    object value = inputControlParameters[i + 1];
+                    object? key = inputControlParameters[i];
+                    object? value = inputControlParameters[i + 1];
                     if (key == null)
                     {
                         throw new InvalidOperationException(SR.Format(SR.UIHintImplementation_ControlParameterKeyIsNull, i));
@@ -185,7 +186,7 @@ namespace System.ComponentModel.DataAnnotations
                     {
                         throw new InvalidOperationException(SR.Format(SR.UIHintImplementation_ControlParameterKeyIsNotAString,
                                                             i,
-                                                            inputControlParameters[i].ToString()));
+                                                            inputControlParameters[i]!.ToString()));
                     }
 
                     if (controlParameters.ContainsKey(keyString))
index cb11bc4..9913f18 100644 (file)
@@ -15,7 +15,7 @@ namespace System.ComponentModel.DataAnnotations
             DefaultErrorMessage = SR.UrlAttribute_Invalid;
         }
 
-        public override bool IsValid(object value)
+        public override bool IsValid(object? value)
         {
             if (value == null)
             {
index 0d7f64c..01ec012 100644 (file)
@@ -22,12 +22,12 @@ namespace System.ComponentModel.DataAnnotations
     {
         #region Member Fields
 
-        private string _errorMessage;
-        private Func<string> _errorMessageResourceAccessor;
-        private string _errorMessageResourceName;
-        private Type _errorMessageResourceType;
+        private string? _errorMessage;
+        private Func<string>? _errorMessageResourceAccessor;
+        private string? _errorMessageResourceName;
+        private Type? _errorMessageResourceType;
         private volatile bool _hasBaseIsValid;
-        private string _defaultErrorMessage;
+        private string? _defaultErrorMessage;
         #endregion
 
         #region All Constructors
@@ -76,7 +76,7 @@ namespace System.ComponentModel.DataAnnotations
         /// This property was added after the public contract for DataAnnotations was created.
         /// It is internal to avoid changing the DataAnnotations contract.
         /// </summary>
-        internal string DefaultErrorMessage
+        internal string? DefaultErrorMessage
         {
             set
             {
@@ -99,7 +99,7 @@ namespace System.ComponentModel.DataAnnotations
             get
             {
                 SetupResourceAccessor();
-                return _errorMessageResourceAccessor();
+                return _errorMessageResourceAccessor!();
             }
         }
 
@@ -127,7 +127,7 @@ namespace System.ComponentModel.DataAnnotations
         ///     This property is intended to be used for non-localizable error messages.  Use
         ///     <see cref="ErrorMessageResourceType" /> and <see cref="ErrorMessageResourceName" /> for localizable error messages.
         /// </value>
-        public string ErrorMessage
+        public string? ErrorMessage
         {
             // If _errorMessage is not set, return the default. This is done to preserve
             // behavior prior to the fix where ErrorMessage showed the non-null message to use.
@@ -154,7 +154,7 @@ namespace System.ComponentModel.DataAnnotations
         ///     Use this property to set the name of the property within <see cref="ErrorMessageResourceType" />
         ///     that will provide a localized error message.  Use <see cref="ErrorMessage" /> for non-localized error messages.
         /// </value>
-        public string ErrorMessageResourceName
+        public string? ErrorMessageResourceName
         {
             get => _errorMessageResourceName;
             set
@@ -175,7 +175,7 @@ namespace System.ComponentModel.DataAnnotations
         ///         Use <see cref="ErrorMessage" /> instead of this pair if error messages are not localized.
         ///     </para>
         /// </value>
-        public Type ErrorMessageResourceType
+        public Type? ErrorMessageResourceType
         {
             get => _errorMessageResourceType;
             set
@@ -199,7 +199,7 @@ namespace System.ComponentModel.DataAnnotations
         {
             if (_errorMessageResourceAccessor == null)
             {
-                string localErrorMessage = ErrorMessage;
+                string? localErrorMessage = ErrorMessage;
                 bool resourceNameSet = !string.IsNullOrEmpty(_errorMessageResourceName);
                 bool errorMessageSet = !string.IsNullOrEmpty(_errorMessage);
                 bool resourceTypeSet = _errorMessageResourceType != null;
@@ -231,7 +231,7 @@ namespace System.ComponentModel.DataAnnotations
                     // Here if not using resource type/name -- the accessor is just the error message string,
                     // which we know is not empty to have gotten this far.
                     // We captured error message to local in case it changes before accessor runs
-                    _errorMessageResourceAccessor = () => localErrorMessage;
+                    _errorMessageResourceAccessor = () => localErrorMessage!;
                 }
             }
         }
@@ -273,7 +273,9 @@ namespace System.ComponentModel.DataAnnotations
                                                     _errorMessageResourceType.FullName));
             }
 
-            _errorMessageResourceAccessor = () => (string)property.GetValue(null, null);
+
+            // TODO-NULLABLE: If the user-provided resource returns null, an ArgumentNullException is thrown - should probably throw a better exception
+            _errorMessageResourceAccessor = () => (string)property.GetValue(null, null)!;
         }
 
         #endregion
@@ -321,7 +323,7 @@ namespace System.ComponentModel.DataAnnotations
         ///     is thrown when neither overload of IsValid has been implemented
         ///     by a derived class.
         /// </exception>
-        public virtual bool IsValid(object value)
+        public virtual bool IsValid(object? value)
         {
             if (!_hasBaseIsValid)
             {
@@ -330,7 +332,10 @@ namespace System.ComponentModel.DataAnnotations
             }
 
             // call overridden method.
-            return IsValid(value, null) == ValidationResult.Success;
+            // The IsValid method without a validationContext predates the one accepting the context.
+            // This is theoretically unreachable through normal use cases.
+            // Instead, the overload using validationContext should be called.
+            return IsValid(value, null!) == ValidationResult.Success;
         }
 
         /// <summary>
@@ -355,7 +360,7 @@ namespace System.ComponentModel.DataAnnotations
         ///     is thrown when <see cref="IsValid(object, ValidationContext)" />
         ///     has not been implemented by a derived class.
         /// </exception>
-        protected virtual ValidationResult IsValid(object value, ValidationContext validationContext)
+        protected virtual ValidationResult? IsValid(object? value, ValidationContext validationContext)
         {
             if (_hasBaseIsValid)
             {
@@ -369,8 +374,8 @@ namespace System.ComponentModel.DataAnnotations
             // call overridden method.
             if (!IsValid(value))
             {
-                string[] memberNames = validationContext.MemberName != null
-                    ? new string[] { validationContext.MemberName }
+                string[]? memberNames = validationContext.MemberName is { } memberName
+                    ? new[] { memberName }
                     : null;
                 result = new ValidationResult(FormatErrorMessage(validationContext.DisplayName), memberNames);
             }
@@ -404,7 +409,7 @@ namespace System.ComponentModel.DataAnnotations
         ///     is thrown when <see cref="IsValid(object, ValidationContext)" />
         ///     has not been implemented by a derived class.
         /// </exception>
-        public ValidationResult GetValidationResult(object value, ValidationContext validationContext)
+        public ValidationResult? GetValidationResult(object? value, ValidationContext validationContext)
         {
             if (validationContext == null)
             {
@@ -445,7 +450,7 @@ namespace System.ComponentModel.DataAnnotations
         ///     is thrown if <see cref="IsValid(object)" /> returns <c>false</c>.
         /// </exception>
         /// <exception cref="InvalidOperationException"> is thrown if the current attribute is malformed.</exception>
-        public void Validate(object value, string name)
+        public void Validate(object? value, string name)
         {
             if (!IsValid(value))
             {
@@ -474,14 +479,14 @@ namespace System.ComponentModel.DataAnnotations
         ///     is thrown when <see cref="IsValid(object, ValidationContext)" />
         ///     has not been implemented by a derived class.
         /// </exception>
-        public void Validate(object value, ValidationContext validationContext)
+        public void Validate(object? value, ValidationContext validationContext)
         {
             if (validationContext == null)
             {
                 throw new ArgumentNullException(nameof(validationContext));
             }
 
-            ValidationResult result = GetValidationResult(value, validationContext);
+            ValidationResult? result = GetValidationResult(value, validationContext);
 
             if (result != null)
             {
index 710bb9d..db3b57b 100644 (file)
@@ -3,6 +3,7 @@
 
 using System.Collections.Generic;
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 using System.Globalization;
 using System.Linq;
 using System.Reflection;
@@ -43,7 +44,7 @@ namespace System.ComponentModel.DataAnnotations
         /// </summary>
         /// <param name="validationContext">The context that describes the type.  It cannot be null.</param>
         /// <returns>The display attribute instance, if present.</returns>
-        internal DisplayAttribute GetTypeDisplayAttribute(ValidationContext validationContext)
+        internal DisplayAttribute? GetTypeDisplayAttribute(ValidationContext validationContext)
         {
             EnsureValidationContext(validationContext);
             var item = GetTypeStoreItem(validationContext.ObjectType);
@@ -59,7 +60,7 @@ namespace System.ComponentModel.DataAnnotations
         {
             EnsureValidationContext(validationContext);
             var typeItem = GetTypeStoreItem(validationContext.ObjectType);
-            var item = typeItem.GetPropertyStoreItem(validationContext.MemberName);
+            var item = typeItem.GetPropertyStoreItem(validationContext.MemberName!);
             return item.ValidationAttributes;
         }
 
@@ -68,11 +69,11 @@ namespace System.ComponentModel.DataAnnotations
         /// </summary>
         /// <param name="validationContext">The context that describes the property.  It cannot be null.</param>
         /// <returns>The display attribute instance, if present.</returns>
-        internal DisplayAttribute GetPropertyDisplayAttribute(ValidationContext validationContext)
+        internal DisplayAttribute? GetPropertyDisplayAttribute(ValidationContext validationContext)
         {
             EnsureValidationContext(validationContext);
             var typeItem = GetTypeStoreItem(validationContext.ObjectType);
-            var item = typeItem.GetPropertyStoreItem(validationContext.MemberName);
+            var item = typeItem.GetPropertyStoreItem(validationContext.MemberName!);
             return item.DisplayAttribute;
         }
 
@@ -85,7 +86,7 @@ namespace System.ComponentModel.DataAnnotations
         {
             EnsureValidationContext(validationContext);
             var typeItem = GetTypeStoreItem(validationContext.ObjectType);
-            var item = typeItem.GetPropertyStoreItem(validationContext.MemberName);
+            var item = typeItem.GetPropertyStoreItem(validationContext.MemberName!);
             return item.PropertyType;
         }
 
@@ -100,8 +101,8 @@ namespace System.ComponentModel.DataAnnotations
         {
             EnsureValidationContext(validationContext);
             var typeItem = GetTypeStoreItem(validationContext.ObjectType);
-            PropertyStoreItem item;
-            return typeItem.TryGetPropertyStoreItem(validationContext.MemberName, out item);
+            PropertyStoreItem? item;
+            return typeItem.TryGetPropertyStoreItem(validationContext.MemberName!, out item);
         }
 
         /// <summary>
@@ -115,7 +116,7 @@ namespace System.ComponentModel.DataAnnotations
 
             lock (_typeStoreItems)
             {
-                if (!_typeStoreItems.TryGetValue(type, out TypeStoreItem item))
+                if (!_typeStoreItems.TryGetValue(type, out TypeStoreItem? item))
                 {
                     // use CustomAttributeExtensions.GetCustomAttributes() to get inherited attributes as well as direct ones
                     var attributes = CustomAttributeExtensions.GetCustomAttributes(type, true);
@@ -158,7 +159,7 @@ namespace System.ComponentModel.DataAnnotations
 
             internal IEnumerable<ValidationAttribute> ValidationAttributes { get; }
 
-            internal DisplayAttribute DisplayAttribute { get; }
+            internal DisplayAttribute? DisplayAttribute { get; }
         }
 
         /// <summary>
@@ -168,7 +169,7 @@ namespace System.ComponentModel.DataAnnotations
         {
             private readonly object _syncRoot = new object();
             private readonly Type _type;
-            private Dictionary<string, PropertyStoreItem> _propertyStoreItems;
+            private Dictionary<string, PropertyStoreItem>? _propertyStoreItems;
 
             internal TypeStoreItem(Type type, IEnumerable<Attribute> attributes)
                 : base(attributes)
@@ -178,7 +179,7 @@ namespace System.ComponentModel.DataAnnotations
 
             internal PropertyStoreItem GetPropertyStoreItem(string propertyName)
             {
-                if (!TryGetPropertyStoreItem(propertyName, out PropertyStoreItem item))
+                if (!TryGetPropertyStoreItem(propertyName, out PropertyStoreItem? item))
                 {
                     throw new ArgumentException(SR.Format(SR.AttributeStore_Unknown_Property, _type.Name, propertyName),
                                                 nameof(propertyName));
@@ -187,7 +188,7 @@ namespace System.ComponentModel.DataAnnotations
                 return item;
             }
 
-            internal bool TryGetPropertyStoreItem(string propertyName, out PropertyStoreItem item)
+            internal bool TryGetPropertyStoreItem(string propertyName, [NotNullWhen(true)] out PropertyStoreItem? item)
             {
                 if (string.IsNullOrEmpty(propertyName))
                 {
index ba91968..f12578a 100644 (file)
@@ -28,9 +28,9 @@ namespace System.ComponentModel.DataAnnotations
     {
         #region Member Fields
 
-        private readonly Dictionary<object, object> _items;
-        private string _displayName;
-        private Func<Type, object> _serviceProvider;
+        private readonly Dictionary<object, object?> _items;
+        private string? _displayName;
+        private Func<Type, object?>? _serviceProvider;
 
         #endregion
 
@@ -57,7 +57,7 @@ namespace System.ComponentModel.DataAnnotations
         ///     new dictionary, preventing consumers from modifying the original dictionary.
         /// </param>
         /// <exception cref="ArgumentNullException">When <paramref name="instance" /> is <c>null</c></exception>
-        public ValidationContext(object instance, IDictionary<object, object> items)
+        public ValidationContext(object instance, IDictionary<object, object?>? items)
             : this(instance, null, items)
         {
         }
@@ -78,7 +78,7 @@ namespace System.ComponentModel.DataAnnotations
         ///     new dictionary, preventing consumers from modifying the original dictionary.
         /// </param>
         /// <exception cref="ArgumentNullException">When <paramref name="instance" /> is <c>null</c></exception>
-        public ValidationContext(object instance, IServiceProvider serviceProvider, IDictionary<object, object> items)
+        public ValidationContext(object instance, IServiceProvider? serviceProvider, IDictionary<object, object?>? items)
         {
             if (instance == null)
             {
@@ -90,7 +90,7 @@ namespace System.ComponentModel.DataAnnotations
                 InitializeServiceProvider(serviceType => serviceProvider.GetService(serviceType));
             }
 
-            _items = items != null ? new Dictionary<object, object>(items) : new Dictionary<object, object>();
+            _items = items != null ? new Dictionary<object, object?>(items) : new Dictionary<object, object?>();
             ObjectInstance = instance;
         }
 
@@ -155,7 +155,7 @@ namespace System.ComponentModel.DataAnnotations
         ///     This name reflects the API name of the member being validated, not a localized name.  It should be set
         ///     only for property or parameter contexts.
         /// </value>
-        public string MemberName { get; set; }
+        public string? MemberName { get; set; }
 
         /// <summary>
         ///     Gets the dictionary of key/value pairs associated with this context.
@@ -164,7 +164,7 @@ namespace System.ComponentModel.DataAnnotations
         ///     This property will never be null, but the dictionary may be empty.  Changes made
         ///     to items in this dictionary will never affect the original dictionary specified in the constructor.
         /// </value>
-        public IDictionary<object, object> Items => _items;
+        public IDictionary<object, object?> Items => _items;
 
         #endregion
 
@@ -174,11 +174,11 @@ namespace System.ComponentModel.DataAnnotations
         ///     Looks up the display name using the DisplayAttribute attached to the respective type or property.
         /// </summary>
         /// <returns>A display-friendly name of the member represented by the <see cref="MemberName" />.</returns>
-        private string GetDisplayName()
+        private string? GetDisplayName()
         {
-            string displayName = null;
+            string? displayName = null;
             ValidationAttributeStore store = ValidationAttributeStore.Instance;
-            DisplayAttribute displayAttribute = null;
+            DisplayAttribute? displayAttribute = null;
 
             if (string.IsNullOrEmpty(MemberName))
             {
@@ -206,7 +206,7 @@ namespace System.ComponentModel.DataAnnotations
         ///     desired <see cref="Type" /> when <see cref="GetService" /> is called.
         ///     If it is <c>null</c>, <see cref="GetService" /> will always return <c>null</c>.
         /// </param>
-        public void InitializeServiceProvider(Func<Type, object> serviceProvider)
+        public void InitializeServiceProvider(Func<Type, object?> serviceProvider)
         {
             _serviceProvider = serviceProvider;
         }
@@ -220,7 +220,7 @@ namespace System.ComponentModel.DataAnnotations
         /// </summary>
         /// <param name="serviceType">The type of the service needed.</param>
         /// <returns>An instance of that service or null if it is not available.</returns>
-        public object GetService(Type serviceType) => _serviceProvider?.Invoke(serviceType);
+        public object? GetService(Type serviceType) => _serviceProvider?.Invoke(serviceType);
 
         #endregion
     }
index efb091e..fc57b1f 100644 (file)
@@ -12,7 +12,7 @@ namespace System.ComponentModel.DataAnnotations
     [System.Runtime.CompilerServices.TypeForwardedFrom("System.ComponentModel.DataAnnotations, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35")]
     public class ValidationException : Exception
     {
-        private ValidationResult _validationResult;
+        private ValidationResult? _validationResult;
 
         /// <summary>
         ///     Constructor that accepts a structured <see cref="ValidationResult" /> describing the problem.
@@ -20,8 +20,8 @@ namespace System.ComponentModel.DataAnnotations
         /// <param name="validationResult">The value describing the validation error</param>
         /// <param name="validatingAttribute">The attribute that triggered this exception</param>
         /// <param name="value">The value that caused the validating attribute to trigger the exception</param>
-        public ValidationException(ValidationResult validationResult, ValidationAttribute validatingAttribute,
-            object value)
+        public ValidationException(ValidationResult validationResult, ValidationAttribute? validatingAttribute,
+            object? value)
             : this(validationResult.ErrorMessage, validatingAttribute, value)
         {
             _validationResult = validationResult;
@@ -33,7 +33,7 @@ namespace System.ComponentModel.DataAnnotations
         /// <param name="errorMessage">The localized error message</param>
         /// <param name="validatingAttribute">The attribute that triggered this exception</param>
         /// <param name="value">The value that caused the validating attribute to trigger the exception</param>
-        public ValidationException(string errorMessage, ValidationAttribute validatingAttribute, object value)
+        public ValidationException(string? errorMessage, ValidationAttribute? validatingAttribute, object? value)
             : base(errorMessage)
         {
             Value = value;
@@ -53,7 +53,7 @@ namespace System.ComponentModel.DataAnnotations
         /// </summary>
         /// <remarks>The long form of this constructor is preferred because it gives better error reporting.</remarks>
         /// <param name="message">The localized message</param>
-        public ValidationException(string message)
+        public ValidationException(string? message)
             : base(message)
         {
         }
@@ -64,7 +64,7 @@ namespace System.ComponentModel.DataAnnotations
         /// <remarks>The long form of this constructor is preferred because it gives better error reporting</remarks>
         /// <param name="message">The localized error message</param>
         /// <param name="innerException">inner exception</param>
-        public ValidationException(string message, Exception innerException)
+        public ValidationException(string? message, Exception? innerException)
             : base(message, innerException)
         {
         }
@@ -82,7 +82,7 @@ namespace System.ComponentModel.DataAnnotations
         /// <summary>
         ///     Gets the <see>ValidationAttribute</see> instance that triggered this exception.
         /// </summary>
-        public ValidationAttribute ValidationAttribute { get; }
+        public ValidationAttribute? ValidationAttribute { get; }
 
         /// <summary>
         ///     Gets the <see cref="ValidationResult" /> instance that describes the validation error.
@@ -96,6 +96,6 @@ namespace System.ComponentModel.DataAnnotations
         /// <summary>
         ///     Gets the value that caused the validating attribute to trigger the exception
         /// </summary>
-        public object Value { get; }
+        public object? Value { get; }
     }
 }
index 5142f18..fa26fd8 100644 (file)
@@ -23,7 +23,7 @@ namespace System.ComponentModel.DataAnnotations
         ///     The <c>null</c> value is used to indicate success.  Consumers of <see cref="ValidationResult" />s
         ///     should compare the values to <see cref="ValidationResult.Success" /> rather than checking for null.
         /// </remarks>
-        public static readonly ValidationResult Success;
+        public static readonly ValidationResult? Success;
 
         #endregion
 
@@ -37,7 +37,7 @@ namespace System.ComponentModel.DataAnnotations
         ///     The user-visible error message.  If null, <see cref="ValidationAttribute.GetValidationResult" />
         ///     will use <see cref="ValidationAttribute.FormatErrorMessage" /> for its error message.
         /// </param>
-        public ValidationResult(string errorMessage)
+        public ValidationResult(string? errorMessage)
             : this(errorMessage, null)
         {
         }
@@ -54,7 +54,7 @@ namespace System.ComponentModel.DataAnnotations
         ///     The list of member names affected by this result.
         ///     This list of member names is meant to be used by presentation layers to indicate which fields are in error.
         /// </param>
-        public ValidationResult(string errorMessage, IEnumerable<string> memberNames)
+        public ValidationResult(string? errorMessage, IEnumerable<string>? memberNames)
         {
             ErrorMessage = errorMessage;
             MemberNames = memberNames ?? Array.Empty<string>();
@@ -88,7 +88,7 @@ namespace System.ComponentModel.DataAnnotations
         /// <summary>
         ///     Gets the error message for this result.  It may be null.
         /// </summary>
-        public string ErrorMessage { get; set; }
+        public string? ErrorMessage { get; set; }
 
         #endregion
 
@@ -107,7 +107,7 @@ namespace System.ComponentModel.DataAnnotations
         ///     The <see cref="ErrorMessage" /> property value if specified,
         ///     otherwise, the base <see cref="object.ToString" /> result.
         /// </returns>
-        public override string ToString() => ErrorMessage ?? base.ToString();
+        public override string ToString() => ErrorMessage ?? base.ToString()!;
         #endregion Methods
     }
 }
index a50329a..b6251f5 100644 (file)
@@ -3,6 +3,7 @@
 
 using System.Collections.Generic;
 using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
 using System.Globalization;
 using System.Linq;
 using System.Reflection;
@@ -46,12 +47,12 @@ namespace System.ComponentModel.DataAnnotations
         ///     When the <see cref="ValidationContext.MemberName" /> of <paramref name="validationContext" /> is not a valid
         ///     property.
         /// </exception>
-        public static bool TryValidateProperty(object value, ValidationContext validationContext,
-            ICollection<ValidationResult> validationResults)
+        public static bool TryValidateProperty(object? value, ValidationContext validationContext,
+            ICollection<ValidationResult>? validationResults)
         {
             // Throw if value cannot be assigned to this property.  That is not a validation exception.
             var propertyType = _store.GetPropertyType(validationContext);
-            var propertyName = validationContext.MemberName;
+            var propertyName = validationContext.MemberName!;
             EnsureValidPropertyType(propertyName, propertyType, value);
 
             var result = true;
@@ -92,7 +93,7 @@ namespace System.ComponentModel.DataAnnotations
         ///     <see cref="ValidationContext.ObjectInstance" />on <paramref name="validationContext" />.
         /// </exception>
         public static bool TryValidateObject(
-            object instance, ValidationContext validationContext, ICollection<ValidationResult> validationResults) =>
+            object instance, ValidationContext validationContext, ICollection<ValidationResult>? validationResults) =>
             TryValidateObject(instance, validationContext, validationResults, false /*validateAllProperties*/);
 
         /// <summary>
@@ -129,13 +130,14 @@ namespace System.ComponentModel.DataAnnotations
         ///     <see cref="ValidationContext.ObjectInstance" />on <paramref name="validationContext" />.
         /// </exception>
         public static bool TryValidateObject(object instance, ValidationContext validationContext,
-            ICollection<ValidationResult> validationResults, bool validateAllProperties)
+            ICollection<ValidationResult>? validationResults, bool validateAllProperties)
         {
             if (instance == null)
             {
                 throw new ArgumentNullException(nameof(instance));
             }
 
+            // TODO-NULLABLE: null validationContext isn't supported (GetObjectValidationErrors will throw), remove that check
             if (validationContext != null && instance != validationContext.ObjectInstance)
             {
                 throw new ArgumentException(SR.Validator_InstanceMustMatchValidationContextInstance, nameof(instance));
@@ -144,7 +146,7 @@ namespace System.ComponentModel.DataAnnotations
             var result = true;
             var breakOnFirstError = (validationResults == null);
 
-            foreach (ValidationError err in GetObjectValidationErrors(instance, validationContext, validateAllProperties, breakOnFirstError))
+            foreach (ValidationError err in GetObjectValidationErrors(instance, validationContext!, validateAllProperties, breakOnFirstError))
             {
                 result = false;
 
@@ -184,7 +186,7 @@ namespace System.ComponentModel.DataAnnotations
         /// </param>
         /// <returns><c>true</c> if the object is valid, <c>false</c> if any validation errors are encountered.</returns>
         public static bool TryValidateValue(object value, ValidationContext validationContext,
-            ICollection<ValidationResult> validationResults, IEnumerable<ValidationAttribute> validationAttributes)
+            ICollection<ValidationResult>? validationResults, IEnumerable<ValidationAttribute> validationAttributes)
         {
             var result = true;
             var breakOnFirstError = validationResults == null;
@@ -211,11 +213,11 @@ namespace System.ComponentModel.DataAnnotations
         /// </param>
         /// <exception cref="ArgumentNullException">When <paramref name="validationContext" /> is null.</exception>
         /// <exception cref="ValidationException">When <paramref name="value" /> is invalid for this property.</exception>
-        public static void ValidateProperty(object value, ValidationContext validationContext)
+        public static void ValidateProperty(object? value, ValidationContext validationContext)
         {
             // Throw if value cannot be assigned to this property.  That is not a validation exception.
             var propertyType = _store.GetPropertyType(validationContext);
-            EnsureValidPropertyType(validationContext.MemberName, propertyType, value);
+            EnsureValidPropertyType(validationContext.MemberName!, propertyType, value);
 
             var attributes = _store.GetPropertyValidationAttributes(validationContext);
 
@@ -343,7 +345,7 @@ namespace System.ComponentModel.DataAnnotations
         /// </param>
         /// <returns><c>true</c> if the assignment is legal.</returns>
         /// <exception cref="ArgumentNullException">When <paramref name="destinationType" /> is null.</exception>
-        private static bool CanBeAssigned(Type destinationType, object value)
+        private static bool CanBeAssigned(Type destinationType, object? value)
         {
             if (value == null)
             {
@@ -364,7 +366,7 @@ namespace System.ComponentModel.DataAnnotations
         /// <param name="propertyType">The type of the property.</param>
         /// <param name="value">The value.  Null is permitted only if the property will accept it.</param>
         /// <exception cref="ArgumentException"> is thrown if <paramref name="value" /> is the wrong type for this property.</exception>
-        private static void EnsureValidPropertyType(string propertyName, Type propertyType, object value)
+        private static void EnsureValidPropertyType(string propertyName, Type propertyType, object? value)
         {
             if (!CanBeAssigned(propertyType, value))
             {
@@ -476,7 +478,7 @@ namespace System.ComponentModel.DataAnnotations
                         var validationResult = reqAttr.GetValidationResult(property.Value, property.Key);
                         if (validationResult != ValidationResult.Success)
                         {
-                            errors.Add(new ValidationError(reqAttr, property.Value, validationResult));
+                            errors.Add(new ValidationError(reqAttr, property.Value, validationResult!));
                         }
                     }
                 }
@@ -500,12 +502,12 @@ namespace System.ComponentModel.DataAnnotations
         ///     value.
         /// </returns>
         /// <remarks>Ignores indexed properties.</remarks>
-        private static ICollection<KeyValuePair<ValidationContext, object>> GetPropertyValues(object instance,
+        private static ICollection<KeyValuePair<ValidationContext, object?>> GetPropertyValues(object instance,
             ValidationContext validationContext)
         {
             var properties = instance.GetType().GetRuntimeProperties()
                                 .Where(p => ValidationAttributeStore.IsPublic(p) && !p.GetIndexParameters().Any());
-            var items = new List<KeyValuePair<ValidationContext, object>>(properties.Count());
+            var items = new List<KeyValuePair<ValidationContext, object?>>(properties.Count());
             foreach (var property in properties)
             {
                 var context = CreateValidationContext(instance, validationContext);
@@ -513,7 +515,7 @@ namespace System.ComponentModel.DataAnnotations
 
                 if (_store.GetPropertyValidationAttributes(context).Any())
                 {
-                    items.Add(new KeyValuePair<ValidationContext, object>(context, property.GetValue(instance, null)));
+                    items.Add(new KeyValuePair<ValidationContext, object?>(context, property.GetValue(instance, null)));
                 }
             }
 
@@ -537,7 +539,7 @@ namespace System.ComponentModel.DataAnnotations
         /// </param>
         /// <returns>The collection of validation errors.</returns>
         /// <exception cref="ArgumentNullException">When <paramref name="validationContext" /> is null.</exception>
-        private static IEnumerable<ValidationError> GetValidationErrors(object value,
+        private static IEnumerable<ValidationError> GetValidationErrors(object? value,
             ValidationContext validationContext, IEnumerable<ValidationAttribute> attributes, bool breakOnFirstError)
         {
             if (validationContext == null)
@@ -546,7 +548,7 @@ namespace System.ComponentModel.DataAnnotations
             }
 
             var errors = new List<ValidationError>();
-            ValidationError validationError;
+            ValidationError? validationError;
 
             // Get the required validator if there is one and test it first, aborting on failure
             var required = attributes.OfType<RequiredAttribute>().FirstOrDefault();
@@ -592,15 +594,15 @@ namespace System.ComponentModel.DataAnnotations
         /// </param>
         /// <returns><c>true</c> if the value is valid.</returns>
         /// <exception cref="ArgumentNullException">When <paramref name="validationContext" /> is null.</exception>
-        private static bool TryValidate(object value, ValidationContext validationContext, ValidationAttribute attribute,
-            out ValidationError validationError)
+        private static bool TryValidate(object? value, ValidationContext validationContext, ValidationAttribute attribute,
+            [NotNullWhen(false)] out ValidationError? validationError)
         {
             Debug.Assert(validationContext != null);
 
             var validationResult = attribute.GetValidationResult(value, validationContext);
             if (validationResult != ValidationResult.Success)
             {
-                validationError = new ValidationError(attribute, value, validationResult);
+                validationError = new ValidationError(attribute, value, validationResult!);
                 return false;
             }
 
@@ -614,10 +616,10 @@ namespace System.ComponentModel.DataAnnotations
         /// </summary>
         private class ValidationError
         {
-            private readonly object _value;
-            private readonly ValidationAttribute _validationAttribute;
+            private readonly object? _value;
+            private readonly ValidationAttribute? _validationAttribute;
 
-            internal ValidationError(ValidationAttribute validationAttribute, object value,
+            internal ValidationError(ValidationAttribute? validationAttribute, object? value,
                 ValidationResult validationResult)
             {
                 _validationAttribute = validationAttribute;