在IEquatable上覆盖等于

时间:2014-11-04 14:29:46

标签: c# .net entity-framework

我有以下方法,我试图阻止人们改变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.VesselsIcollection<Vessel>中产生3个容器,其中一个容器的VesselId为6,这恰好是currentVessel的VesselId但是匹配失败,方法返回false

我已经对类似的SO问题和MSDN文档做了一些阅读,我对这里发生的事情的理解是因为ICollection中ID为6的Vessel是我试图匹配的currentVessel的不同实例,引用导致不相等,并且与相等规则有关的内容不基于ID。

我的Person模型包含public virtual ICollection<Vessel> Vessels { get; set; }这是否意味着我必须在IEquatable模型上实现Vessel接口,然后覆盖Equals方法。

在此实例中,我希望基于id的自定义规则具有相等性。如何覆盖此方法?

3 个答案:

答案 0 :(得分:3)

在这种情况下覆盖Equals似乎有点矫枉过正,为什么不做呢

currentPerson.Vessels.Any(x => x.ID == currentVessel.ID)

答案 1 :(得分:2)

@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>可以转换为许多Generics集合,如List<T> for例。

来自MSDN

调用多个通用集合对象的搜索方法时。其中一些类型及其方法包括以下内容:

  • BinarySearch方法的一些泛型重载。
  • List类的搜索方法,包括List.Contains(T),List.IndexOf,List.LastIndexOf和List.Remove。
  • Dictionary类的搜索方法,包括ContainsKey和Remove。 通用LinkedList类的搜索方法,包括LinkedList.Contains和Remove。

答案 2 :(得分:1)

更改

if (currentPerson.Vessels.Contains(currentVessel))
{
    return true;
}
else
    return false;

return currentPerson.Vessels.Any(x => x.ID == currentVessel.ID)