class 列表之间的 C# 区别
C# difference between list of a class
我无法区分 C# 中的 2 个列表。
我怎样才能得到差异?我尝试了 Except 但我没有得到我想要的结果。
例如:
这些产品是账单的一部分
class Product {
public int id_prod;
public int quantity;
public float price;
}
Product prd1 = new Product(){1,2,34};
Product prd2 = new Product(){2,5,20};
Product prd3 = new Product(){3,6,14};
Product prd4 = new Product(){4,9,8};
Product prd5 = new Product(){5,12,70};
Product prd1b = new Product(){1,60,34};
List<Product> oldLst = new List<Product>(){ prd1,prd2,prd3};
List<Product> newLst = new List<Product>(){ prd1b,prd2,prd4,prd5};
请注意,旧 prd1 和新 prd1 之间的数量可能会发生变化
我的问题是当我使用 var lstToDel = oldLst.Except(newLst);
lstToDel 填入 oldLst 并没有区别
期望的结果是
lstToDel = new List<Product>(){prd1,prd3};
Except 也接受 IEqualityComparer。创建一个以确定哪些产品是 "equal",这意味着具有相同的属性。查看更多:https://msdn.microsoft.com/en-us/library/bb336390.aspx
您应该覆盖产品上的平等并定义您的标准来比较产品。或者定义你的
class MyComparer: IEqualityComparer<Product>
{
}
如果您看到实现,您应该注意到它使用了 Equals,因此创建您的 Comparer,您将在调用 Except
时获得所需的结果
/// <typeparam name="T">The type of objects to compare.This type parameter is contravariant. That is, you can use either the type you specified or any type that is less derived. For more information about covariance and contravariance, see Covariance and Contravariance in Generics.</typeparam>
[__DynamicallyInvokable]
public interface IEqualityComparer<in T>
{
/// <summary>
/// Determines whether the specified objects are equal.
/// </summary>
///
/// <returns>
/// true if the specified objects are equal; otherwise, false.
/// </returns>
/// <param name="x">The first object of type <paramref name="T"/> to compare.</param><param name="y">The second object of type <paramref name="T"/> to compare.</param>
[__DynamicallyInvokable]
bool Equals(T x, T y);
/// <summary>
/// Returns a hash code for the specified object.
/// </summary>
///
/// <returns>
/// A hash code for the specified object.
/// </returns>
/// <param name="obj">The <see cref="T:System.Object"/> for which a hash code is to be returned.</param><exception cref="T:System.ArgumentNullException">The type of <paramref name="obj"/> is a reference type and <paramref name="obj"/> is null.</exception>
[__DynamicallyInvokable]
int GetHashCode(T obj);
}
}
这是 Except 实现
[__DynamicallyInvokable]
public static IEnumerable<TSource> Except<TSource>(this IEnumerable<TSource> first, IEnumerable<TSource> second, IEqualityComparer<TSource> comparer)
{
if (first == null)
throw Error.ArgumentNull("first");
if (second == null)
throw Error.ArgumentNull("second");
else
return Enumerable.ExceptIterator<TSource>(first, second, comparer);
}
您还可以定义自己的通用扩展方法,如下所示:
public static IEnumerable<T> Except<T>(this IEnumerable<T> collection, IEnumerable<T> comparand, Func<T, object> comparer)
{
return collection.Except(comparand, new FuncComparer<T>(comparer));
}
使用自定义比较器:
public class FuncComparer<T> : IEqualityComparer<T>
{
private readonly Func<T, object> _comparer;
public FuncComparer(Func<T, object> comparer)
{
_comparer = comparer;
}
public bool Equals(T x, T y)
{
return _comparer(x) == _comparer(y);
}
public int GetHashCode(T obj)
{
return _comparer(obj).GetHashCode();
}
}
然后你可以像这样使用它:
var lstToDel = oldLst.Except(newLst, x=>x.id_prod); // your comparer logic is on id_prod property
然而,这仅适用于简单的 属性 比较。
对于更复杂的相等比较器,最好制作您自己的自定义 IEqualityComparer。
我无法区分 C# 中的 2 个列表。
我怎样才能得到差异?我尝试了 Except 但我没有得到我想要的结果。
例如: 这些产品是账单的一部分
class Product {
public int id_prod;
public int quantity;
public float price;
}
Product prd1 = new Product(){1,2,34};
Product prd2 = new Product(){2,5,20};
Product prd3 = new Product(){3,6,14};
Product prd4 = new Product(){4,9,8};
Product prd5 = new Product(){5,12,70};
Product prd1b = new Product(){1,60,34};
List<Product> oldLst = new List<Product>(){ prd1,prd2,prd3};
List<Product> newLst = new List<Product>(){ prd1b,prd2,prd4,prd5};
请注意,旧 prd1 和新 prd1 之间的数量可能会发生变化
我的问题是当我使用 var lstToDel = oldLst.Except(newLst);
lstToDel 填入 oldLst 并没有区别
期望的结果是
lstToDel = new List<Product>(){prd1,prd3};
Except 也接受 IEqualityComparer。创建一个以确定哪些产品是 "equal",这意味着具有相同的属性。查看更多:https://msdn.microsoft.com/en-us/library/bb336390.aspx
您应该覆盖产品上的平等并定义您的标准来比较产品。或者定义你的
class MyComparer: IEqualityComparer<Product>
{
}
如果您看到实现,您应该注意到它使用了 Equals,因此创建您的 Comparer,您将在调用 Except
时获得所需的结果/// <typeparam name="T">The type of objects to compare.This type parameter is contravariant. That is, you can use either the type you specified or any type that is less derived. For more information about covariance and contravariance, see Covariance and Contravariance in Generics.</typeparam>
[__DynamicallyInvokable]
public interface IEqualityComparer<in T>
{
/// <summary>
/// Determines whether the specified objects are equal.
/// </summary>
///
/// <returns>
/// true if the specified objects are equal; otherwise, false.
/// </returns>
/// <param name="x">The first object of type <paramref name="T"/> to compare.</param><param name="y">The second object of type <paramref name="T"/> to compare.</param>
[__DynamicallyInvokable]
bool Equals(T x, T y);
/// <summary>
/// Returns a hash code for the specified object.
/// </summary>
///
/// <returns>
/// A hash code for the specified object.
/// </returns>
/// <param name="obj">The <see cref="T:System.Object"/> for which a hash code is to be returned.</param><exception cref="T:System.ArgumentNullException">The type of <paramref name="obj"/> is a reference type and <paramref name="obj"/> is null.</exception>
[__DynamicallyInvokable]
int GetHashCode(T obj);
}
}
这是 Except 实现
[__DynamicallyInvokable]
public static IEnumerable<TSource> Except<TSource>(this IEnumerable<TSource> first, IEnumerable<TSource> second, IEqualityComparer<TSource> comparer)
{
if (first == null)
throw Error.ArgumentNull("first");
if (second == null)
throw Error.ArgumentNull("second");
else
return Enumerable.ExceptIterator<TSource>(first, second, comparer);
}
您还可以定义自己的通用扩展方法,如下所示:
public static IEnumerable<T> Except<T>(this IEnumerable<T> collection, IEnumerable<T> comparand, Func<T, object> comparer)
{
return collection.Except(comparand, new FuncComparer<T>(comparer));
}
使用自定义比较器:
public class FuncComparer<T> : IEqualityComparer<T>
{
private readonly Func<T, object> _comparer;
public FuncComparer(Func<T, object> comparer)
{
_comparer = comparer;
}
public bool Equals(T x, T y)
{
return _comparer(x) == _comparer(y);
}
public int GetHashCode(T obj)
{
return _comparer(obj).GetHashCode();
}
}
然后你可以像这样使用它:
var lstToDel = oldLst.Except(newLst, x=>x.id_prod); // your comparer logic is on id_prod property
然而,这仅适用于简单的 属性 比较。 对于更复杂的相等比较器,最好制作您自己的自定义 IEqualityComparer。