{"record":{"id":"8fd4cca82d54d9cf","repo":"dotnet/csharplang","slug":"empty-names-not-allowed","errorCode":null,"errorMessage":"Empty names not allowed","messagePattern":"Empty names not allowed","errorType":"exception","errorClass":"ArgumentException","httpStatus":null,"severity":"error","filePath":"proposals/final-initializers.md","lineNumber":44,"sourceCode":"\n``` c#\npublic class Person\n{\n    public required string FirstName { get; init; }\n    public string? MiddleName { get; init; }\n    public required string LastName { get; init; }\n\n    private readonly string fullName;\n\n    init\n    {\n        // Fix up provided state\n        FirstName = FirstName.Trim();\n        MiddleName = MiddleName?.Trim();\n        LastName = LastName.Trim();\n\n        // Validate state\n        if (FirstName is \"\") throw new ArgumentException(\"Empty names not allowed\", nameof(FirstName));\n        if (LastName is \"\") throw new ArgumentException(\"Empty names not allowed\", nameof(LastName));\n\n        // Compute additional state\n        fullName = (MiddleName is null)\n            ? $\"{FirstName} {LastName}\"\n            : $\"{FirstName} {MiddleName} {LastName}\";\n    }\n\n    public override string ToString() => fullName;\n}\n```\n\n### Syntax\n\nThis production is added to `class_member_declaration`, etc.:\n\n``` antlr\nfinal_initializer_declaration","sourceCodeStart":26,"sourceCodeEnd":62,"githubUrl":"https://github.com/dotnet/csharplang/blob/05eb4800fc3dc76259ccd49ac01f1eeb49222380/proposals/final-initializers.md#L26-L62","documentation":"Thrown inside an `init` accessor of a `Person`-like class in the final-initializers proposal when `FirstName` or `LastName` is the empty string after trimming. It is a post-fixup state validation: the init accessor trims the incoming value and then rejects empty results. The offending property name is passed via `nameof`, so the exception points at the specific property.","triggerScenarios":"Object-initializing the type with `FirstName` or `LastName` set to \"\" or to an all-whitespace string (which trims to \"\"). Initializing from parsed input or a record mapping that did not enforce non-emptiness.","commonSituations":"Form/API input containing only spaces; CSV/deserialization producing empty cells mapped to required name fields; trimmed UI fields submitted blank; migration/import jobs with sparse data.","solutions":["Trim and check for emptiness before constructing/initializing, and reject with a user-facing message at the input boundary.","Provide a non-empty default or normalize blanks to null and adapt the type's nullability contract accordingly.","Validate at the data-source (form, DTO, parser) so empty values never reach the init accessor.","If empty is legitimately allowed for a name, relax the rule in the init accessor and adjust tests."],"exampleFix":"// before\nvar p = new Person { FirstName = \" \", LastName = \"Smith\" };\n\n// after\nstring first = userInput?.Trim() ?? \"\";\nif (first is \"\") throw new ArgumentException(\"First name required\", nameof(userInput));\nvar p = new Person { FirstName = first, LastName = \"Smith\" };","handlingStrategy":"validation","validationCode":"static string RequireName(string value, string paramName)\n{\n    string trimmed = value?.Trim() ?? \"\";\n    if (trimmed is \"\") throw new ArgumentException(\"Name must not be empty.\", paramName);\n    return trimmed;\n}","typeGuard":"static bool IsNonEmptyName(string value) => !string.IsNullOrWhiteSpace(value);","tryCatchPattern":"try { var p = new Person { FirstName = first, LastName = last }; }\ncatch (ArgumentException ex) when (ex.ParamName is nameof(first) or nameof(last))\n{\n    // surface a field-specific validation error to the caller/UI\n}","preventionTips":["Trim and reject blank strings at the input/parsing boundary, not in the init accessor.","Use `string.IsNullOrWhiteSpace` checks for any required text field.","Validate DTOs with data annotations or a validation pipeline before mapping to domain types."],"tags":["validation","init-only","string","csharp"],"backgroundTag":null,"analyzedSha":"05eb4800fc3dc76259ccd49ac01f1eeb49222380","analyzedAt":"2026-08-13T17:44:03.908Z","schemaVersion":2},"datasetVersion":"2026-08-13T19:17:28.613Z"}