简体   繁体   中英

How to compare the same properties of two different class objects in C#?

I have two classes A and B which have some properties that are the same. I am looking for a way to compare only the same properties and was hoping if there was some nuget package that did this for any type of class.

I don't know how to go about looking for such a nuget package, I already tried using if statements to compare the same properties, but I have a lot of cases like this so it would be easier to use a nuget package to do it.

Also, it is not possible to include inheritance here , as the two classes are not logically linked.

class A {
  string title;
  DateTime publishDate;
  string Author;
  int numberOfSales;
}
class B {
  DateTime publishDate;
  int numberOfSales;
}

I have already did something like this to compare the two same properties

if (A.publishDate.Equals(B.publishDate)) {
  // Do something
}
if (A.numberOfSales == B.numberOfSales) {
  // Do something
}

I would really be grateful if someone could let me know if there is some nuget package that would just compare the same properties of the two classes.

Why you don't use native interface in c# ?

you can use Icomprable interface like this :

 public class A:IComparable<B>
        {
            public string title;
            public DateTime publishDate;
            public string Author;
            public int numberOfSales;
            public int CompareTo(B other)
            {
                if (this.numberOfSales == other.numberOfSales && this.publishDate.Equals(other.publishDate))
                    return 0;
                if (this.numberOfSales != other.numberOfSales && this.publishDate.Equals(other.publishDate))
                    return 1;
                if (this.numberOfSales == other.numberOfSales && !this.publishDate.Equals(other.publishDate))
                    return 2;
                return -1;
            }
        }
        public class B
        {
            public DateTime publishDate;
            public int numberOfSales;
        }

then you can use it like this :

  switch (aClass.CompareTo(bClass))
            {
                case 0:Console.WriteLine("both properties are equal");break;
                case 1:Console.WriteLine("PublishDate only equal"); break;
                case 2: Console.WriteLine("NumberOfSales only equal"); break;
                case -1: Console.WriteLine("None are equal"); break;
            }

I hope it will be useful

Just use Reflection.

For example, this class will all fields (because your sample class listings have no Properties , they only have Fields ) and return a list of them:

using System;
using System.Linq;
using System.Collections.Generic;
using System.Reflection;

public static class Comparer {
        public static List<String> Compare<T1, T2>(T1 a, T2 b) {
            var result = new List<String>(); // you can choose to return FieldInfo or values or whatever...
            // you can also use .GetProperties() if you actually want Properties with getters.
            var aFields = typeof(T1).GetFields(BindingFlags.Instance | BindingFlags.Public);
            var bFields = typeof(T2).GetFields(BindingFlags.Instance | BindingFlags.Public);

            var aCommonFields = new List<FieldInfo>();
            var bCommonFields = new List<FieldInfo>();

            Func<IEnumerable<FieldInfo>, FieldInfo, bool> predicate = (other, x) => other.FirstOrDefault(z => z.Name == x.Name && z.FieldType == x.FieldType) != null;

            aCommonFields.AddRange(aFields.Where(x => predicate(bFields, x)));

            bCommonFields.AddRange(bFields.Where(x => predicate(aCommonFields, x)));

            foreach(var aCommonField in aCommonFields) {
                var bCommonField = bCommonFields.First(bField => predicate(new[]{ aCommonField }, bField));
                var aValue = aCommonField.GetValue(a);
                var bValue = bCommonField.GetValue(b);
                if (aValue.Equals(bValue)) {
                    result.Add(aCommonField.Name);
                }
            }

            return result;
        }
    }

Sample usage:

                var a1 = new A { numberOfSales = 42 };
                var b2 = new B { numberOfSales = 42 };
                var commons = Comparer.Compare(a1, b2);

                foreach(var common in commons) {
                    if (common == nameof(A.numberOfSales)) {
                        Console.WriteLine("Number of sales match!");
                    }
                }

I like a more controlled way better where you just type the compaire properties as you did in your sample, perhaps use an icomparable interface.

he reflection option that is offered and will be offered is slow, could give null pointer exceptions etc but write once work always, it's not a nuget package but here you go.

public static List<PropertyInfo> GetDifferences(object test1, object test2)
{
    if (test1 is null)
        throw new ArgumentNullException(nameof(test1));
    if (test2 is null)
        throw new ArgumentNullException(nameof(test2));

    List<PropertyInfo> differences = new List<PropertyInfo>();
    foreach (PropertyInfo property in test1.GetType().GetProperties())
    {
        if (test2.GetType().GetProperties().Any(a => a.Name.Equals(property.Name, StringComparison.Ordinal)))
        {
            object value1 = property.GetValue(test1, null);
            object value2 = property.GetValue(test2, null);
            if ((value1 == null) || !value1.Equals(value2))
            {
                differences.Add(property);
            }
        }
    }
    return differences;
}

It will return the properties that both have and are not the same.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM