1

I am using reflection to compare objects of a given class. I only want to compare certain properties. Right now I have a simple collection of strings with the names of the properties that I want to compare.

Something like:

public static readonly ICollection<string> PROPERTIES_TO_COMPARE = new List<string>()
{
     "Name",
     "Phone"
};

Then I use it doing something like:

PropertyInfo[] properties = typeof(MyClass).GetProperties();
foreach (PropertyInfo property in properties)
{
     if (PROPERTIES_TO_COMPARE.Contains(property.Name))
     {
         //compare
     }
 }

But if next month I change the property name from "Phone" to "PhoneNumber" I will need to remember to edit the collection of properties. I do not find myself to be that trustworthy.

Is there a better way? Perhaps something similar to nameof(varible), so the compiler can help me? Or perhaps my entire approach is wrong?

Update: This is what I need to do (ideally with less code):

 if (oldVersion.Name != newVersion.Name)
 {
        changes.Add(new Change()
        {
              FieldName = nameof(oldVersion.Name),
              OldValue = oldVersion.Name,
              NewValue = newVersion.Name
        });
  }

  if (oldVersion.Phone != newVersion.Phone)
  {
        changes.Add(new Change()
        {
             FieldName = nameof(oldVersion.Phone),
             OldValue = oldVersion.Phone,
             NewValue = newVersion.Phone
        });
  }
  // and 15 properties more
Gelu
  • 955
  • 2
  • 11
  • 21
  • 3
    My spidey-sense is tingling. I doubt this is a good use for reflection. You're likely better off referencing the properties directly instead of going through reflection. –  Apr 22 '21 at 14:11
  • 2
    If you know the type of `myClass` why are you using reflection? This would make sense if you have no compile time knowledge of the type of the objects you are trying to compare... – InBetween Apr 22 '21 at 14:17
  • @InBetween because I am a lazy bastard and the code is much more succint this way. I need to compare 17 properties and list the changes. I did not have the mental fortitude to code that much. But then, like Rainbow Dash says, my spidey-sense started bothering me. I will probably go back to the long but safe solution. I asked just in case I was missing a third option. – Gelu Apr 22 '21 at 14:23
  • 2
    @Gelu "_because I am a lazy bastard_" then you should do this properly, because it will reduce future maintenance effort.. – Johnathan Barclay Apr 22 '21 at 14:26
  • 1
    @Gelu `I need to compare 17 properties and list the changes` Without using reflection, can you give us a small example, with say 3 properties, that gives you the output you expect or need? We can give better guidance with more context and a practical example. –  Apr 22 '21 at 14:26
  • 1
    Firstly, you know the type because you're doing `typeof(MyClass)` so not sure why use reflection. Secondly, if you change the property name next week, you would need to update the collection as you say and you may forget. That's because you're doing it the wrong way. Let the compiler help you if you change the property name: maybe override the `Equals` method and put all the code for equality there. If you change the property name, and forget to update `Equals` method, compiler will tell you. Btw don't be `a lazy bastard` ;) – CodingYoshi Apr 22 '21 at 14:34
  • I added an example. I did not explain myself too well. I don't need to check if they are equal, I need to list the differences. – Gelu Apr 22 '21 at 14:42
  • 1
    @Gelu Does this help you? https://stackoverflow.com/questions/4951233/compare-two-objects-and-find-the-differences –  Apr 22 '21 at 14:50
  • @RainbowDash the thing is that I don't want to compare all properties. Just some of them. Hence the list. – Gelu Apr 22 '21 at 14:58

1 Answers1

2

You can use nameof(MyClass.Name) instead of "Name", and nameof(MyClass.Phone) instead of "Phone", which solves the rename problem. However, honestly, I'd do instead:

static bool ConsideredEqual(MyClass x, MyClass y)
    => x.Name == y.Name && x.Phone == y.Phone;

and use that method instead of all the reflection code - exactly the same maintenance overhead, but much much faster than reflection.

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • nameof(MyClass.Phone) <- That is what I needed! Somehow I didn't know it worked with classes and somehow (even more shameful) it did not occur to my to try it. Thaks a lot! – Gelu Apr 22 '21 at 15:05