{"record":{"id":"c5981166df920fc8","repo":"louthy/language-ext","slug":"eq-attribute-should-have-a-struct-type-that-derives-from","errorCode":null,"errorMessage":"Eq attribute should have a struct type that derives from LanguageExt.Traits.Eq<> passed as its argument","messagePattern":"Eq attribute should have a struct type that derives from LanguageExt\\.Traits\\.Eq<> passed as its argument","errorType":"exception","errorClass":"Exception","httpStatus":null,"severity":"error","filePath":"LanguageExt.Core/DataTypes/Record/Attributes.cs","lineNumber":27,"sourceCode":"\npublic class NonHashAttribute : Attribute;\n\npublic class NonEqAttribute : Attribute;\n\npublic class NonOrdAttribute : Attribute;\n\npublic class NonShowAttribute : Attribute;\n\npublic class EqAttribute : Attribute\n{\n    public EqAttribute(Type type)\n    {\n        if (!type.GetTypeInfo()\n                 .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","sourceCodeStart":9,"sourceCodeEnd":45,"githubUrl":"https://github.com/louthy/language-ext/blob/2f0e3628242889774d4141960a35671a0280051f/LanguageExt.Core/DataTypes/Record/Attributes.cs#L9-L45","documentation":"The `[Eq]` attribute on a LanguageExt record declares which type provides equality for the record. Its constructor validates that the supplied `Type` implements `LanguageExt.Traits.Eq<>`; if the passed type doesn't implement that interface, it throws `Exception(\"Eq attribute should have a struct type that derives from LanguageExt.Traits.Eq<> passed as its argument\")` at attribute instantiation time.","triggerScenarios":"Annotating a record with `[Eq(typeof(MyEq))]` where `MyEq` does not implement `Eq<T>` (e.g. it implements `IEquatable<T>`, `EqualityComparer<T>`, or `Ord<T>` instead), or passing a non-struct/wrong type. The exception surfaces when the attribute is constructed/reflected over.","commonSituations":"Migrating from older LanguageExt `Eq`/`Ord` interfaces to `LanguageExt.Traits.Eq<>` without updating attribute types; copy-pasting an `Ord` provider into an `[Eq]` attribute; typos creating a provider with the wrong base interface.","solutions":["Make the passed type a struct implementing `LanguageExt.Traits.Eq<TRecord>`: `public readonly struct MyEq : Eq<MyRecord> { ... }`.","If you intended ordering, use `[Ord(typeof(...))]` with an `Ord<T>` implementation instead.","Check the LanguageExt version's trait namespace (`LanguageExt.Traits.Eq<>`) matches your provider's interface."],"exampleFix":"// before\npublic class MyEq { } // no Eq<T>\n[Eq(typeof(MyEq))]\npublic partial record Person(string Name);\n\n// after\npublic readonly struct MyEq : Eq<Person>\n{\n    public bool Equals(Person x, Person y) => x.Name == y.Name;\n    public int GetHashCode(Person x) => x.Name?.GetHashCode() ?? 0;\n}\n[Eq(typeof(MyEq))]\npublic partial record Person(string Name);","handlingStrategy":"validation","validationCode":"bool isValidEqProvider(Type t) =>\n    t.IsValueType &&\n    t.GetInterfaces().Any(i => i.IsGenericType && i.GetGenericTypeDefinition() == typeof(LanguageExt.Traits.Eq<>));","typeGuard":"bool IsValidEqAttributeArg(Type t) =>\n    t.GetInterfaces().Any(i => i.ToString().StartsWith(\"LanguageExt.Traits.Eq`1\"));","tryCatchPattern":"try { var attr = new EqAttribute(typeof(MyEq)); }\ncatch (Exception ex) when (ex.Message.StartsWith(\"Eq attribute should have\")) { /* fix the provider type */ }","preventionTips":["Always define Eq providers as structs implementing LanguageExt.Traits.Eq<T>.","Don't reuse Ord providers in [Eq] attributes; keep separate types.","Add a unit test that instantiates every record attribute to fail fast at CI time."],"tags":["records","attributes","equality","csharp"],"backgroundTag":"invalid-constructor-argument","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"}