{"record":{"id":"daa505af210e999d","repo":"louthy/language-ext","slug":"ord-attribute-should-have-a-struct-type-that-derives-from","errorCode":null,"errorMessage":"Ord attribute should have a struct type that derives from LanguageExt.Traits.Ord<> passed as its argument","messagePattern":"Ord attribute should have a struct type that derives from LanguageExt\\.Traits\\.Ord<> passed as its argument","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"LanguageExt.Core/DataTypes/Record/Attributes.cs","lineNumber":41,"sourceCode":"                 .ImplementedInterfaces\n                 .AsIterable()     \n                 .Exists(i => i.ToString().StartsWith(\"LanguageExt.Traits.Eq`1\")))\n        {\n            throw new Exception(\"Eq attribute should have a struct type that derives from LanguageExt.Traits.Eq<> passed as its argument\");\n        }\n    }\n}\n\npublic class OrdAttribute : Attribute\n{\n    public OrdAttribute(Type type)\n    {\n        if (!type.GetTypeInfo()\n                 .ImplementedInterfaces\n                 .AsIterable()\n                 .Exists(i => i.ToString().StartsWith(\"LanguageExt.Traits.Ord`1\")))\n        {\n            throw new Exception(\"Ord attribute should have a struct type that derives from LanguageExt.Traits.Ord<> passed as its argument\");\n        }\n    }\n}\n\npublic class HashableAttribute : Attribute\n{\n    public HashableAttribute(Type type)\n    {\n        if (!type.GetTypeInfo()\n                 .ImplementedInterfaces\n                 .AsIterable()\n                 .Exists(i => i.ToString().StartsWith(\"LanguageExt.Traits.Hashable`1\")))\n        {\n            throw new Exception(\"Hashable attribute should have a struct type that derives from LanguageExt.Traits.Hashable<> passed as its argument\");\n        }\n    }\n}\n","sourceCodeStart":23,"sourceCodeEnd":59,"githubUrl":"https://github.com/louthy/language-ext/blob/2f0e3628242889774d4141960a35671a0280051f/LanguageExt.Core/DataTypes/Record/Attributes.cs#L23-L59","documentation":"OrdAttribute.Validate is applied to the type passed to the [Ord] attribute and throws unless that type implements LanguageExt.Traits.Ord<T>. The [Ord] attribute on a Record must point at a struct that provides ordering semantics for the record; anything else makes the generated comparison invalid.","triggerScenarios":"Decorating a record with [Ord(typeof(X))] where X does not implement LanguageExt.Traits.Ord<T> (or implements the old LanguageExt.Ord<T> interface), so the interface check for a name starting with \"LanguageExt.Traits.Ord`1\" fails.","commonSituations":"Migrating from LanguageExt 3.x/4.x (where Ord lived in a different namespace) to 5.x Traits namespace; pointing the attribute at a class instead of a struct; pointing it at the record itself instead of a separate comparer type.","solutions":["Make the type passed to [Ord] a struct that implements LanguageExt.Traits.Ord<T> for your record type T.","If migrating, update the comparer to the LanguageExt.Traits.Ord<T> interface (new namespace and shape) instead of the legacy Ord<T>.","Ensure the comparer is a struct, not a class, as required by the attribute contract."],"exampleFix":"// before\n[Ord(typeof(MyOrd))]  // MyOrd implements old LanguageExt.Ord<Rec>\npublic partial record Rec(int X);\n\n// after\npublic readonly struct MyOrd : LanguageExt.Traits.Ord<Rec>\n{\n    public int Compare(Rec x, Rec y) => x.X.CompareTo(y.X);\n}\n[Ord(typeof(MyOrd))]\npublic partial record Rec(int X);","handlingStrategy":"validation","validationCode":"// before applying the attribute\ntypeof(MyOrd).GetInterfaces().Any(i =>\n    i.IsGenericType && i.GetGenericTypeDefinition() == typeof(LanguageExt.Traits.Ord<>));","typeGuard":"static bool IsValidOrdComparer<T>(T t) => t is LanguageExt.Traits.Ord<RecordType>;","tryCatchPattern":null,"preventionTips":["Always define Ord comparers as structs implementing LanguageExt.Traits.Ord<T>.","After LanguageExt upgrades, re-check comparer interfaces compile against Traits.","Add a unit test that constructs an attributed record to surface attribute validation early."],"tags":["csharp","languageext","records","attributes","reflection"],"backgroundTag":"invalid-argument-value","analyzedSha":"2f0e3628242889774d4141960a35671a0280051f","analyzedAt":"2026-09-15T03:31:55.716Z","contentChangedAt":"2026-09-15T03:31:55.716Z","schemaVersion":2},"datasetVersion":"2026-09-16T09:17:16.951Z"}