重写IEquatable上的Equals
本文关键字:Equals 上的 IEquatable 重写 | 更新日期: 2023-09-27 18:28:58
我尝试使用以下方法来阻止人们更改querystring
以查看其他人的详细信息:
public static bool IsCurrentUserAuthorisedVessel(HttpRequest request)
{
Guid currentUser = GetCurrentUserId();
PersonRepository repo = new PersonRepository();
VesselRepository vesselRepo = new VesselRepository();
Person currentPerson = repo.GetPersonByUser(currentUser);
int qs = int.Parse(request.QueryString["VesselId"]);
Vessel currentVessel = vesselRepo.GetVessel(qs);
if (!String.IsNullOrEmpty(request.QueryString["VesselId"]))
{
if (IsCurrentUserAdmin())
{
return true; //Always return true for admin
}
else
{
if (currentPerson.Vessels.Contains(currentVessel))
{
return true;
}
else
return false;
}
}
return true;
}
在我当前调试的示例中,currentPerson.Vessels
在Icollection<Vessel>
中产生3个容器,其中一个容器的VesselId
为6,恰好也是currentVessel
的VesselId,但是匹配失败,该方法返回false
。
我已经阅读了一些类似的SO问题和MSDN文档,我对这里发生的事情的理解是,因为ICollection中ID为6的船只是我试图匹配的当前船只的不同实例,引用导致不相等,并且与相等规则有关的事情不是基于ID的。
我的Person
模型包含public virtual ICollection<Vessel> Vessels { get; set; }
,这是否意味着我必须在Vessel
模型上实现IEquatable
接口,然后重写Equals方法。
在这个例子中,我想要我自己的基于id的自定义规则。如何覆盖此方法?
在这种情况下重写Equals
似乎有点过头了,为什么不直接执行呢
currentPerson.Vessels.Any(x => x.ID == currentVessel.ID)
@james提出的解决方案不是最佳实践。为什么如果你有一长串应该添加到Hashset<Vessel>
包含的容器的列表,方法将只花费O(1)
,因为它将在GetHashCode
上索引,而.Any
是一个扩展方法,应该迭代所有元素以找到正确的元素,并且成本将是O(n)
你可以做一些类似的事情
public class Vessel : IEquatable<Vessel>
{
public int Id { get; set; }
public bool Equals(Vessel other)
{
return Id == other.Id ;
}
public override int GetHashCode()
{
return Id;
}
public override bool Equals(object obj)
{
var vessel = obj as Vessel;
return vessel != null && vessel.Id == this.Id;
}
}
更新
我之所以说这不是最佳实践,是因为OP说他有一个ICollection<Vessel>
,可以转换成许多泛型集合,例如List<T>
。
来自MSDN
当调用多个通用集合对象的搜索方法时。其中一些类型及其方法包括:
- BinarySearch方法的一些通用重载
- List类的搜索方法,包括List.Contains(T)、List.IndexOf、List.LastIndexOf和List.Remove
- Dictionary类的搜索方法,包括ContainsKey和Remove。通用LinkedList类的搜索方法,包括LinkedList.Contains和Remove
更改
if (currentPerson.Vessels.Contains(currentVessel))
{
return true;
}
else
return false;
至
return currentPerson.Vessels.Any(x => x.ID == currentVessel.ID)