0

In short:

Is there any way to provide my own Equals( object? ) method for a record struct instead of being stuck with the one automagically generated by the compiler?

Note:

This question has nothing to do with replacing the automatically generated MyRecord.Equals( MyRecord ) method, which is trivially doable; This question is specifically about replacing the MyRecord.Equals( Object? ) method inherited from Object, which is a whole different story.

Background:

If I want to override Equals( object? ) in plain old class and struct, I am free to do so; however, I cannot do it with record; the IDE says "Member with the same signature is already declared", while the compiler gives "error CS0111: Type 'Color' already defines a member called 'Equals' with the same parameter types".

A quick look at official Microsoft documentation here and here says that this is by design.

The Question:

Does anyone know any workaround to this?

(Besides just never using record and forfeiting all of its convenience.)

Mike Nakis
  • 56,297
  • 11
  • 110
  • 142
  • _"To somewhat mitigate this problem, in every class that I have the need to override object.Equals( object? ) I make sure to declare it with [System.Obsolete] so that it cannot be accidentally invoked."_ - personally I would try to write a analyzer to achieve this goal. – Guru Stron Mar 11 '23 at 10:02
  • Also can you please show the trick with the obsolete attribute - cause I was not able to make it work [with my initial attempt](https://sharplab.io/#v2:CYLg1APgAgTAjAWAFDKnAnACgGIHteYB2ApgO4AEAsgJ4DCANgIYDOzmAlADTkBEcP7dgG5kyAEb565PARoMWzcgGNuaAAzK47cgF4AfMoB0AUQCOAV0b02SrSJRJmAFwBO5pU6p0mrcsgDeyOTB5ADaAPJizLj0xE7EmDwKjDzcrubE7AC6QSFQAMzkuABuxC4uAJbAxOQSMeRmltaYuGIAVsQeAPxF7ey5wYFIISPkaFhwk8IDo1AA7LUsxCYWVmytbdPDIQC+MwVFpeVVNRWEngDicQASLAAWtLjVHLp6M6Mf5E53LrgUJBQAHK4JwASQAtgAHWLg4jnYjAYwADyUxEhTgquEIHHsOyAA) – Guru Stron Mar 11 '23 at 10:15
  • @GuruStron thanks for thinking along with me. When I follow the link you provided I see that you have in fact been able to make it work; is there something I am missing? – Mike Nakis Mar 11 '23 at 11:31
  • You only get that warning about obsolete member overriding non-obsolete member, which as I have already said, needs to be suppressed. I use `System.Obsolete` without any arguments, but whatever suits you. – Mike Nakis Mar 11 '23 at 11:31
  • What I have tried to show is that applying `Obsolete` attribute to override does not prevent the `object.Equals` from being used. – Guru Stron Mar 11 '23 at 12:26
  • @GuruStron Okay, I am sorry, I must have not made myself clear. The problem is not with `struct`, it is with `record struct`, (also with `record class`,) and it is not caused by the obsolete attribute; the ability to add the obsolete attribute is simply my reason for wanting to redefine the compiler-synthesized `Equals( object? )` method. Which is something that the compiler does not let me do in a `record struct`. – Mike Nakis Mar 11 '23 at 14:06
  • I mean based on my attempt adding the attribute is pointless, so I asked how do you achieve your goal with it. – Guru Stron Mar 11 '23 at 14:30
  • @GuruStron I'll be damned, I can't get it to reproduce. When invoking the `Equals( object? )` method, the compiler does not issue a warning that it has been deprecated. Maybe that's why it issues the warning when deprecating the method. There is a possibility that I carried the obsoleting habit over from Java, where it works. (I believe it does. Now I can't trust anything anymore.) I will modify the question to remove all mentions of obsolete, since it is not crucial: the question of how can one supply their own `Equals( object? )` method still stands. – Mike Nakis Mar 11 '23 at 14:57
  • @GuruStron this is what seems to be happening: the compiler does not issue a warning when invoking an intentionally obsoleted `Equals( object? )` method, ***but*** while typing the invocation, ReSharper's auto-completion ***does*** show the method name with strike-through styling. – Mike Nakis May 24 '23 at 08:50

1 Answers1

1
  1. Is there any way to provide my own `Equals(object?) method for a record struct instead of being stuck with the one automagically generated by the compiler?

    No, it is not, as the record structs spec says:

    The record struct includes a synthesized override equivalent to a method declared as follows:

    public override readonly bool Equals(object? obj);
    

    It is an error if the override is declared explicitly.

  2. Does anyone know any workaround to this?

    You can try looking into some assembly weaving with something like Fody, but as far as I understand this happens after compilation, so it will not cover all possible scenarios (i.e. would not work for the same assembly usage).

    Personally I would look into dumping the ObsoleteAttribute approach and trying to implement Roslyn analyzer which will handle the type mismatch problem you are trying to solve.

Guru Stron
  • 102,774
  • 10
  • 95
  • 132