我的这个班级DNS_Log
有四个属性。我已经创建了一个这些对象的列表,我试图过滤这些对象仅用于不同的事件。 (当填充列表时,有很多重复)
此处列出了正在填充的商家信息:
dnsLogs.Add( new DNS_Log { Destination = destination,
Source_IP = sourceIp,
Domain_Controller = domainController,
DateTime = datetime });
这是我试图过滤掉不同的那些:
dnsLogs = dnsLogs.Distinct().ToList();
为什么这不起作用?我是否需要在不同的参数中使用一些linq表达式?我想将对象作为一个整体来比较它们的属性。有没有更简单的方法呢?
P.S。我已经开始制作一个似乎工作正常的自定义IEqualityComparer<DNS_Log>
,但我不知道如何在这种情况下实现它。
答案 0 :(得分:5)
您有多种选择:
DNS_Log
IEquatable<T>
注意!在下面的所有代码中,相等性检查假定==
运算符知道如何处理每种类型。对于DateTime成员来说肯定是这样(假设它的也是类型的DateTime),但我显然不能保证其他人会工作。如果Destination成员拥有尚未定义==
运算符的类型,则可能会执行错误操作。由于您还没有为此比较器实施发布自己的代码,因此无法知道该怎么做。
IEquatable<T>
public class DNS_Log : IEquatable<DNS_Log>
{
public bool Equals(DNS_Log other)
{
if (other == null)
return false;
return (other.Destination == Destination
&& other.Source_IP == Source_IP
&& other.Domain_Controller == Domain_Controller
&& other.DateTime == DateTime);
}
public override int GetHashCode()
{
int hash = 23;
hash = hash * 59 + (Destination == null ? 0 : Destination.GetHashCode());
hash = hash * 59 + (Source_IP == null ? 0 : Source_IP.GetHashCode());
hash = hash * 59 + (Domain_Controller == null ? 0 : Domain_Controller.GetHashCode());
hash = hash * 59 + DateTime.GetHashCode();
return hash;
}
}
public class DNS_Log
{
public override bool Equals(object obj)
{
if (obj == null) return false;
var other = obj as DNS_Log;
if (other == null) return false;
... rest the same as above
IEqualityComparer<T>
最后,您可以在致电Distinct
时提供IEqualityComparer<T>:
dnsLogs = dnsLogs.Distinct(new DNS_LogEqualityComparer()).ToList();
public class DNS_LogEqualityComparer : IEqualityComparer<DNS_Log>
{
public int GetHashCode(DNS_Log obj)
{
int hash = 23;
hash = hash * 59 + (obj.Destination == null ? 0 : obj.Destination.GetHashCode());
hash = hash * 59 + (obj.Source_IP == null ? 0 : obj.Source_IP.GetHashCode());
hash = hash * 59 + (obj.Domain_Controller == null ? 0 : obj.Domain_Controller.GetHashCode());
hash = hash * 59 + obj.DateTime.GetHashCode();
return hash;
}
public bool Equals(DNS_Log x, DNS_Log y)
{
if (ReferenceEquals(x, y)) return true;
if (x == null) return false;
return (x.Destination == y.Destination
&& x.Source_IP == y.Source_IP
&& .Domain_Controller == y.Domain_Controller
&& x.DateTime == y.DateTime);
}
}
答案 1 :(得分:2)
你基本上有三个选择:
IEqualityComparer<DNS_Log>
时提供您的自定义Distinct
(类似dnsLogs.Distinct(myEqualityComparerInstance).ToList();
DNS_Log
实施IEquatable<DNS_Log>
Equals
GetHashCode
和DNS_Log
答案 2 :(得分:1)
为什么这不起作用?
它不起作用,因为Distinct
使用GetHashCode
+ Equals
来比较对象。由于您没有从对象覆盖这些方法,因此您将获得仅比较引用的默认实现。
所以你有几个选择:
Distinct
IEqualityComparer<T>
Equals
+ GethashCode
不需要创建新类或修改现有类的另一种(效率较低)方法是使用匿名类型的内置GetHashCode
+ Equals
和{ {1}}:
Enumerable.GroupBy
这是第二种方法的一个例子:
IEnumerable<DNS_Log> distinctLogs =
from dns in dnsLogs
group dns by new { dns.Destination, dns.Source_IP,dns.Domain_Controller, dns.DateTime } into g
select g.First(); // change logic if you don't want an arbitrary object(first)
public class DNS_Log
{
public string Destination{ get; set; }
public int Source_IP { get; set; }
public string Domain_Controller { get; set; }
public DateTime DateTime { get; set; }
public override bool Equals(object obj)
{
DNS_Log c2 = obj as DNS_Log;
if (obj == null) return false;
return Destination == c2.Destination && Source_IP == c2.Source_IP
&& Domain_Controller == c2.Domain_Controller && DateTime == c2.DateTime;
}
public override int GetHashCode()
{
unchecked
{
int hash = 17;
hash = hash * 23 + Destination.GetHashCode();
hash = hash * 23 + Source_IP;
hash = hash * 23 + Domain_Controller.GetHashCode();
hash = hash * 23 + DateTime.GetHashCode();
return hash;
}
}
}
- 类({方法)的Equals
和GethashCode
类似。