C# 如何创建一个通用方法来比较任意类型的两个列表。类型也可以是类的列表

C# 如何创建一个通用方法来比较任意类型的两个列表。类型也可以是类的列表,c#,list,generics,C#,List,Generics,下面是一节课 public class Attribute { public string Name { get; set; } public string Value { get; set; } } 下面是我的main方法中的代码 { var test = new List<Attribute>(); test.Add(new Attribute { Name = "Don", Val

下面是一节课

public class Attribute
    {
        public string Name { get; set; }
        public string Value { get; set; }
    }
下面是我的main方法中的代码

{
            var test = new List<Attribute>();
            test.Add(new Attribute { Name = "Don", Value = "21" });
            test.Add(new Attribute { Value = "34", Name = "Karthik" });


            var test1 = new List<Attribute>();
            test1.Add(new Attribute { Name = "Don", Value = "21" });
            test1.Add(new Attribute { Value = "34", Name = "Karthik" });

            var obj = new Program();
            var areEqual1 = obj.CompareList<List<Attribute>>(test, test1);
}
{
var test=新列表();
添加(新属性{Name=“Don”,Value=“21”});
添加(新属性{Value=“34”,Name=“Karthik”});
var test1=新列表();
test1.Add(新属性{Name=“Don”,Value=“21”});
test1.Add(新属性{Value=“34”,Name=“Karthik”});
var obj=新程序();
var areEqual1=对象比较列表(测试,测试1);
}
我有一个合作伙伴的方法

public bool CompareList<T>(T firstList, T secondList) where T : class
        {
            var list1 = firstList as IList<T>;

            return true;

        }
public bool比较列表(T firstList,T secondList),其中T:class
{
var list1=作为IList的第一个列表;
返回true;
}

现在,list1的值为null。我知道.net不允许我们这样做。但是有没有其他方法可以让我发布这个通用列表呢。我的目的是比较这两个列表的每个属性值。我正在使用反射来获取属性,但只有当我能够将firstlist/secondlist转换为可枚举的内容时,它才能工作。如果我直接在
IList
firstList
作为
IList
)中使用类的名称,它会起作用,但如果我给出
,则不会起作用。请提供帮助。

更改方法的签名,然后删除多余的强制转换:

public bool CompareList<T>(IList<T> firstList, IList<T> secondList) where T : class
{
    var list1 = firstList as IList<T>; // Cast is not necessary any more
    return true;
}
public bool比较列表(IList firstList,IList secondList),其中T:class
{
var list1=firstList as IList;//不再需要强制转换
返回true;
}

只需创建按列表类型参数化的方法。此外,您还可以创建用于比较任何类型集合的方法:

public bool CompareSequences<T> (IEnumerable<T> first, IEnumerable<T> second,
      Comparer<T> comparer = null)
{
    comparer = comparer ?? Comparer<T>.Default;

    if (first == null)
        throw new ArgumentNullException(nameof(first));

    if (second == null)
        throw new ArgumentNullException(nameof(second));

    var firstIterator = first.GetEnumerator();
    var secondIterator = second.GetEnumerator();

    while(true)
    {
        bool firstHasItem = firstIterator.MoveNext();
        bool secondHasItem = secondIterator.MoveNext();

        if (firstHasItem != secondHasItem)
            return false;

        if (!firstHasItem && !secondHasItem)
            return true;

        if (comparer.Compare(firstIterator.Current, secondIterator.Current) != 0)
            return false;
    }
}
或者您可以创建并传递比较器实例。您可以创建比较器,它使用反射来比较某些类型的字段/属性。但它并不像你想象的那么简单——属性可以是复杂的类型或集合

用法:

var areEqual1 = obj.CompareSequences(test, test1);

如果您不需要比较具有复杂结构的对象(具有内部集合和其他自定义对象),则可以使用类似以下的比较器:

public class SimplePropertiesComparer<T> : Comparer<T>
{
    public override int Compare (T x, T y)
    {
        Type type = typeof(T);
        var flags = BindingFlags.GetProperty | BindingFlags.Public | BindingFlags.Instance;

        foreach (var property in type.GetProperties(flags))
        {
            var propertyType = property.PropertyType;
            if (!typeof(IComparable).IsAssignableFrom(propertyType))
               throw new NotSupportedException($"{propertyType} props are not supported.");

            var propertyValueX = (IComparable)property.GetValue(x);
            var propertyValueY = (IComparable)property.GetValue(y);

            if (propertyValueX == null && propertyValueY == null)
                continue;

            if (propertyValueX == null)
                return -1;

            int result = propertyValueX.CompareTo(property.GetValue(y));
            if (result == 0)
                continue;

            return result;
        }

        return 0;
    }
}
公共类SimpleProperties Comparer:Comparer
{
公共覆盖整型比较(TX,TY)
{
类型=类型(T);
var flags=BindingFlags.GetProperty | BindingFlags.Public | BindingFlags.Instance;
foreach(type.GetProperties(标志)中的var属性)
{
var propertyType=property.propertyType;
如果(!typeof(IComparable).IsAssignableFrom(propertyType))
抛出新的NotSupportedException($“{propertyType}道具不受支持。”);
var propertyValueX=(IComparable)property.GetValue(x);
var propertyvalue=(IComparable)property.GetValue(y);
if(propertyValueX==null&&propertyValueY==null)
继续;
if(propertyValueX==null)
返回-1;
int result=propertyValueX.CompareTo(property.GetValue(y));
如果(结果==0)
继续;
返回结果;
}
返回0;
}
}
并将其传递给序列比较器

var equal = obj.CompareSequences(test, test1, new SimplePropertiesComparer<Attribute>());
var equal=obj.CompareSequences(test,test1,新的SimpleProperties Comparer());
公共布尔比较目录(列表1、列表2)
{
尝试
{
如果(T的类型)等于(U的类型)
{
//用于检查空列表
if(list1==null&&list2==null)
返回true;
if(list1==null | | list2==null)
抛出新异常(“其中一个列表为空”);
if(list1.Count.Equals(list2.Count))
{
类型=类型(T);
//对于基本列表
if(类型为IsPrimitive)
{
int标志=0;
for(int i=0;i

此方法可用于基元列表和引用列表。请尝试此方法。它将比较列表的类型、计数和成员。

我已按照您的建议执行了操作,但在调用CompareList方法时,它会这样说:“类型泛型,列表不能用作泛型类型或方法中的类型参数“T”
var equal = obj.CompareSequences(test, test1, new SimplePropertiesComparer<Attribute>());
public bool CompareGenericLists<T, U>(List<T> list1, List<U> list2)
    {
        try
        {

            if (typeof(T).Equals(typeof(U)))
            {
                //For checking null lists
                if (list1 == null && list2 == null)
                    return true;
                if (list1 == null || list2 == null)
                    throw new Exception("One of the Lists is Null");

                if (list1.Count.Equals(list2.Count))
                {
                    Type type = typeof(T);

                    //For primitive lists
                    if (type.IsPrimitive)
                    {
                        int flag = 0;

                        for (int i = 0; i < list1.Count; i++)
                        {
                            if (list1.ElementAt(i).Equals(list2.ElementAt(i)))
                                flag++;
                        }
                        if (flag != list1.Count)
                            throw new Exception("Objects values are not same");

                }

                    //For Reference List
                    else
                    {
                        for (int i = 0; i < list1.Count; i++)
                        {
                            foreach (System.Reflection.PropertyInfo property in type.GetProperties())
                            {
                                string Object1Value = string.Empty;
                                string Object2Value = string.Empty;

                                Object1Value = type.GetProperty(property.Name).GetValue(list1.ElementAt(i)).ToString();
                                Object2Value = type.GetProperty(property.Name).GetValue(list2.ElementAt(i)).ToString();

                                if (Object1Value != Object2Value)
                                {
                                    throw new Exception("Objects values are not same");
                                }

                            }
                        }
                    }
                }
                else
                throw new Exception("Length of lists is not Same");
            }
            else
            throw new Exception("Different type of lists");
        }
        catch(Exception ex)
        {
            throw ex;
        }
            return true; 
    }