TIL: The new Keyword Doesn't Hide Data Annotations

In another episode of I thought I knew enough about C#…

Today I wanted to “overwrite” the validations of a property from a parent DTO on its child DTO. Let’s say I had a Movie and Clip and needed shorter names for clips.

Just take a look at the attributes on Movie and ShortClip.

using System.ComponentModel.DataAnnotations;

namespace TestProject1;

[TestClass]
public class NewKeywordTests
{
    public abstract class Movie
    {
        [Required]
        [MinLength(52)]  // <--
        public string? Name { get; set; }
    }

    public class ShortClip : Movie
    {
        [MaxLength(20)]  // <-- Different annotations
        public new string? Name { get; set; }
		//     ^^^
    }

    [TestMethod]
    public void NewDoesNotHideValidationAttributes()
    {
        var myClip = new ShortClip
        {
            Name = "AShortName"
			//     ^^^^^
			// It has less than 20 chars,
			// so it must be valid, right?
        };

        var context = new ValidationContext(myClip);
        var validationResults = new List<ValidationResult>();

        bool isValid = Validator.TryValidateObject(
            myClip,
            context,
            validationResults,
            validateAllProperties: true
        );

        Assert.IsTrue(isValid);
        //     ^^^^^
        // Booom!!!
    }
}

Whaaat?! It didn’t work. The new keyword in the child class hides the property, but not the attributes. Sad trombone!

Sneaking into TryValidateObject() source code, it uses TypeDescriptor.GetProperties() to list the properties to validate, which returns a “merged” list of attributes. [Source].

var descriptor = TypeDescriptor.GetProperties(myClip.GetType());
var attributes = x[0].Attributes;
//  ^^^^^
// Among other attributes:
// RequiredAttribute
// MinAttribute
// MaxAttribute

When I asked Gemini for help, it suggested using virtual and override. And guess what? That doesn’t work either.

On my original code, I ended pulling down the property I wanted to have different annotations to the child classes on the hierarchy.

That’s why you shouldn’t blindly trust AI and build code reading and troubleshooting skills. I cover those skills and more in Street-Smart Coding—A roadmap with 30 lessons to help you code like a pro.