#c#
#c#
Вопрос:
у меня есть несколько объектов, у каждого объекта есть точка, я создал для нее словарь (я не уверен, что это лучшая практика), теперь я хочу получить точку на основе значения, вот что я сделал
var x = new Dictionary< EnemisEntity,int>()
{
{new EnemisEntity{enemyType="banzai_Bill"},200 },
{new EnemisEntity{enemyType="beach_koopa" },400 },
{new EnemisEntity{enemyType="big_boo"},800 },
{new EnemisEntity{enemyType="blargg"},1600 },
};
var m= x.FirstOrDefault(f => f.Key.Equals("big_boo")).value;
я должен вернуть мне 800, но это дает мне 0, не могли бы вы, пожалуйста, сказать мне, прежде всего, правильно ли я поступаю, и, во-вторых, почему это дает мне ноль
Комментарии:
1. @BradleyUffner могу я спросить о преимуществе?
Ответ №1:
Вы можете изменить свой код на:
var m = x.FirstOrDefault(f => f.Key.enemyType.Equals("big_boo")).Value;
В вашем выражении фильтра f => f.Key.Equals("big_boo")
f
a KeyValuePair
имеет Key
тип EnemisEntity
, поэтому сравнение его со строкой with object.Equals
дает вам false и FirstOrDefault
возвращает значение по умолчанию KeyValuePair<EnemisEntity, int>
, которое представляет собой структуру со Value
свойством, инициализированным значением default int
— 0
.
Без дополнительного контекста (как используется этот словарь) трудно утверждать, какой дизайн будет более подходящим, другими вариантами являются — переопределение Equals
EnemisEntity
или изменение словаря Dictionary<string, int>
.
Ответ №2:
Если у вас есть Dictionary
, не используйте FirstOrDefault
. Это будет выполнять линейный поиск до тех пор, пока он не удовлетворит Predicate
отрицанию преимуществ Dictionary
постоянного времени поиска. Вам нужно использовать TryGetValue
on Dictionary
или одну из эквивалентных функций поиска.
Чтобы использовать TryGetValue
и использовать весь ваш класс в качестве ключа, вам придется переопределить Equals
и GetHashCode
заставить это работать
public class EnemisEntity
{
public string enemyType { get; set; }
public override bool Equals(object obj)
{
if (!(obj is EnemisEntity entity)) return false;
return ReferenceEquals(this, obj) || string.Equals(enemyType, entity.enemyType);
}
public override int GetHashCode()
{
return HashCode.Combine(enemyType);
}
}
теперь вы можете сделать это
var x = new Dictionary<EnemisEntity, int>()
{
{new EnemisEntity{enemyType="banzai_Bill"},200 },
{new EnemisEntity{enemyType="beach_koopa" },400 },
{new EnemisEntity{enemyType="big_boo"},800 },
{new EnemisEntity{enemyType="blargg"},1600 },
};
if (x.TryGetValue(new EnemisEntity { enemyType = "big_boo" }, out var value))
{
//do something with your int value
}
Однако, похоже, вас интересует только сопоставление enemyType
с an int
, поэтому я бы изменил свой Dictionary
на использование string
в качестве ключа, а не EnemisEntity
потому, что это упрощает все
Комментарии:
1. Создание нового
EnemisEntity
экземпляра каждый раз, когда вам нужно выполнить поиск в словаре, кажется неправильным. Это увеличивает нагрузку на сборщик мусора. Однако я не голосую против, потому что в некоторых случаях это может быть допустимым вариантом.2. Я согласен, именно поэтому я предложил string в качестве ключа