简体   繁体   English

如何在C#中比较两个不同类对象的相同属性?

[英]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. 我有两个类A和B,它们的某些属性是相同的。 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. 我正在寻找一种仅比较相同属性的方法,并希望是否有一些nuget软件包可以对任何类型的类进行此操作。

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. 我不知道如何去寻找这样的nuget包,我已经尝试过使用if语句来比较相同的属性,但是我有很多这样的情况,所以使用nuget包来做会更容易。

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. 如果有人可以让我知道是否有一些nuget软件包可以比较两个类的相同属性,我将不胜感激。

Why you don't use native interface in c# ? 为什么不在c#中使用本机接口?

you can use Icomprable interface like this : 您可以像这样使用Icomprable接口:

 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: 例如,此类将所有字段(因为您的示例类列表没有Properties ,而它们只有Fields )并返回它们的列表:

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. 我喜欢更好地控制的方式,您可以像在样本中一样键入compaire属性,也许使用可比较的界面。

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. 提供和将要提供的反射选项很慢,可能会给null指针异常等,但是总是写一次,它不是nuget包,但是您可以使用。

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. 它将返回具有和不相同的属性。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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