У меня есть следующий метод, который я пытаюсь использовать, чтобы остановить людей, изменяющих 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
Урожайность 3 судна в качестве Icollection<Vessel>
один из которых имеет VesselId
из 6, который также случается быть VesselId из currentVessel
однако матч не удается, и метод возвращает false
.
Я прочитал некоторые аналогичные вопросы SO и документацию MSDN, и мое понимание того, что происходит здесь, состоит в том, что судно, имеющее идентификатор 6 в ICollection, является другим экземпляром текущего сосуда, который я пытаюсь сопоставить, в результате получается ссылка в не равных и что-то связанное с правилами равенства не основано на ID.
Модель My Person
содержит public virtual ICollection<Vessel> Vessels { get; set; }
public virtual ICollection<Vessel> Vessels { get; set; }
public virtual ICollection<Vessel> Vessels { get; set; }
означает ли это, что я должен реализовать интерфейс IEquatable
на моей модели Vessel
а затем переопределить метод Equals.
Я хочу, чтобы мои собственные правила, основанные на id для равенства в этом экземпляре. Как переопределить этот метод?
Переопределение Equals
в этой ситуации кажется немного переборщиваемым здесь, почему бы просто не сделать
currentPerson.Vessels.Any(x => x.ID == currentVessel.ID)
Решение, предложенное @james, не является лучшей практикой. вот почему, если у вас есть длинный список сосудов, который должен быть добавлен в Hashset<Vessel>
то Hashset<Vessel>
будет стоить только O(1)
поскольку он будет проиндексирован на GetHashCode
while. .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>
.
из MSDN
Когда вызывается метод поиска нескольких общих объектов коллекции. Некоторые из этих типов и их методы включают следующее:
return Id == other.Id
equals до: return Id == other.Id
и объект будет равен return to return vessel != null && Equals(vessel)
. Меньше кода, и вы не дублируете логику.
Any
здесь - это « не хорошее решение » или « не лучшая практика », не имеет смысла. Аргумент для реализации Equals
, безусловно, действителен, но только если фактор / размер списка является фактором - который OP не упомянул.
изменение
if (currentPerson.Vessels.Contains(currentVessel))
{
return true;
}
else
return false;
в
return currentPerson.Vessels.Any(x => x.ID == currentVessel.ID)