Переопределение равных на IEquatable

1

У меня есть следующий метод, который я пытаюсь использовать, чтобы остановить людей, изменяющих 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 для равенства в этом экземпляре. Как переопределить этот метод?

  • 0
    Пожалуйста, добавьте тег используемой вами ORM (Entity Framework, NHibernate и т. Д.).
Теги:
entity-framework

3 ответа

3
Лучший ответ

Переопределение Equals в этой ситуации кажется немного переборщиваемым здесь, почему бы просто не сделать

currentPerson.Vessels.Any(x => x.ID == currentVessel.ID)
  • 0
    Спасибо, но сейчас я чувствую себя идиотом. Легко, когда ты знаешь, как эй!
2

Решение, предложенное @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

Когда вызывается метод поиска нескольких общих объектов коллекции. Некоторые из этих типов и их методы включают следующее:

  • Некоторые из общих перегрузок метода BinarySearch.
  • Методы поиска класса List, включая List.Contains(T), List.IndexOf, List.LastIndexOf и List.Remove.
  • Методы поиска класса Dictionary, включая ContainsKey и Remove. Методы поиска общего класса LinkedList, включая LinkedList.Contains и Remove.
  • 0
    Упростите return Id == other.Id equals до: return Id == other.Id и объект будет равен return to return vessel != null && Equals(vessel) . Меньше кода, и вы не дублируете логику.
  • 1
    Утверждать, что использование Any здесь - это « не хорошее решение » или « не лучшая практика », не имеет смысла. Аргумент для реализации Equals , безусловно, действителен, но только если фактор / размер списка является фактором - который OP не упомянул.
Показать ещё 1 комментарий
1

изменение

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

в

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

Ещё вопросы

Сообщество Overcoder
Наверх
Меню