如何创建一个泛型方法来比较任何类型的两个列表.类型也可以是类列表
本文关键字:类型 列表 两个 也可以 任何 创建 何创建 一个 泛型方法 比较 | 更新日期: 2023-09-27 18:35:21
下面是一个类
public class Attribute
{
public string Name { get; set; }
public string Value { get; set; }
}
以下是我的主方法中的代码
{
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);
}
我有一个ComapreList方法
public bool CompareList<T>(T firstList, T secondList) where T : class
{
var list1 = firstList as IList<T>;
return true;
}
现在,list1 具有空值。我知道.net不允许我们这样做。但是有没有其他方法可以投射这个通用列表。我的目的是比较这两个列表的每个属性值。我正在使用反射来获取属性,但仅当我可以将第一个列表/第二个列表转换为可枚举的内容时,它才有效。如果我直接在IList<>
中使用类的名称(firstList
IList<Attribute>
),它可以工作,但如果我给<T>
则不行。请帮忙。
只需创建按列表项目类型类型参数化的方法。更重要的是,您可以创建比较任何类型的集合的方法:
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;
}
}
如果集合项是基元类型,则可以使用默认比较器。但是,如果集合包含自定义项,则需要通过集合项类型实现任一IComparable
:
public class Attribute : IComparable<Attribute>
{
public string Name { get; set; }
public string Value { get; set; }
public int CompareTo (Attribute other)
{
int result = Name.CompareTo(other.Name);
if (result == 0)
return Value.CompareTo(other.Value);
return result;
}
}
或者,您可以创建并传递比较器实例。您可以创建使用反射来比较某种类型的字段/属性的比较器。但它并不像你想象的那么简单 - 属性可以是复杂的类型或集合。
用法:
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;
}
}
并将其传递给序列比较器
var equal = obj.CompareSequences(test, test1, new SimplePropertiesComparer<Attribute>());
更改方法的签名并删除多余的强制转换:
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 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;
}
此方法可用于基元列表和引用列表。请尝试此方法。它将比较列表的类型、计数和成员。