Containskey VS Try Catch
У меня есть список сгенерированных Vector2, я должен проверить по словарю, чтобы увидеть, если они существуют, эта функция выполняется каждый тик.
который будет работать быстрее / лучше сделать так?
public static bool exists(Vector2 Position, Dictionary<Vector2, object> ToCheck)
{
try
{
object Test = ToCheck[Position];
return (true);
}
catch
{
return (false);
}
}
Или я должен придерживаться нормы?
public static bool exists(Vector2 Position, Dictionary<Vector2, object> ToCheck)
{
if (ToCheck.ContainsKey(Position))
{
return (true);
}
return (false);
}
Спасибо за вклад:)
Примечание: (Значение для ключа на данном этапе не имеет значения, иначе я бы использовал TryGetValue вместо ContainsKey)
4 ответа
Определенно используйте ContainsKey
проверять; обработка исключений может добавить большие накладные расходы.
Бросать исключения могут отрицательно повлиять на производительность. Для кода, который обычно терпит неудачу, вы можете использовать шаблоны проектирования, чтобы минимизировать проблемы с производительностью.
Исключения не предназначены для использования в условиях, которые вы можете проверить.
Я рекомендую прочитать документацию MSDN об исключениях в целом и об обработке исключений в частности.
Я знаю, что это старый вопрос, но просто добавить немного эмпирических данных...
Выполнение 50 000 000 просмотров в словаре с 10 000 записей и сравнение относительного времени для завершения:
..Если каждый просмотр успешен:
- прямой (неконтролируемый) забег занимает 1,2 секунды
- защищенный (ContainsKey) забег занимает 2 секунды
- обработанный (try-catch) запуск занимает 1,21 секунды
..Если 1 из каждых 10 000 поисков не выполняется:
- защищенный (ContainsKey) забег занимает 2 секунды
- обработанный (try-catch) пробег занимает 1,37 секунды
..if 16 из каждых 10 000 поисков не удаются:
- защищенный (ContainsKey) забег занимает 2 секунды
- обработанный (try-catch) запуск занимает 3,27 секунды
..Если 250 из каждых 10 000 поисков не пройдены:
- защищенный (ContainsKey) забег занимает 2 секунды
- обработанный (try-catch) запуск занимает 32 секунды
... так что защищенный тест добавит постоянные накладные расходы и ничего более, и тест try-catch будет работать почти так же быстро, как и любой тест, если он никогда не завершится неудачей, но убивает производительность пропорционально количеству сбоев.
Код, который я использовал для запуска тестов:
using System;
using System.Collections.Generic;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{ Test(0);
Test(1);
Test(16);
Test(250);
}
private static void Test(int failsPerSet)
{ Dictionary<int, bool> items = new Dictionary<int,bool>();
for(int i = 0; i < 10000; i++)
if(i >= failsPerSet)
items[i] = true;
if(failsPerSet == 0)
RawLookup(items, failsPerSet);
GuardedLookup(items, failsPerSet);
CaughtLookup(items, failsPerSet);
}
private static void RawLookup
( Dictionary<int, bool> items
, int failsPerSet
){ int found = 0;
DateTime start ;
Console.Write("Raw (");
Console.Write(failsPerSet);
Console.Write("): ");
start = DateTime.Now;
for(int i = 0; i < 50000000; i++)
{ int pick = i % 10000;
if(items[pick])
found++;
}
Console.WriteLine(DateTime.Now - start);
}
private static void GuardedLookup
( Dictionary<int, bool> items
, int failsPerSet
){ int found = 0;
DateTime start ;
Console.Write("Guarded (");
Console.Write(failsPerSet);
Console.Write("): ");
start = DateTime.Now;
for(int i = 0; i < 50000000; i++)
{ int pick = i % 10000;
if(items.ContainsKey(pick))
if(items[pick])
found++;
}
Console.WriteLine(DateTime.Now - start);
}
private static void CaughtLookup
( Dictionary<int, bool> items
, int failsPerSet
){ int found = 0;
DateTime start ;
Console.Write("Caught (");
Console.Write(failsPerSet);
Console.Write("): ");
start = DateTime.Now;
for(int i = 0; i < 50000000; i++)
{ int pick = i % 10000;
try
{ if(items[pick])
found++;
}
catch
{
}
}
Console.WriteLine(DateTime.Now - start);
}
}
}
Примечание: (Значение для ключа на данном этапе не имеет значения, иначе я бы использовал TryGetValue вместо ContainsKey)
Ответ, который вы приняли, является правильным, но просто добавьте, если вам важен только ключ, а не значение, возможно, вы ищете HashSet
а не Dictionary
?
Кроме того, ваш второй фрагмент кода является методом, который буквально добавляет нулевое значение. Просто используйте ToCheck.ContainsKey(Position)
, не создавайте метод, который просто вызывает этот метод и возвращает его значение, но больше ничего не делает.
Никогда не используйте try/catch как часть вашего обычного пути к программе. Это действительно дорого и должно отлавливать только ошибки, которые вы не можете предотвратить. ContainsKey это путь сюда.
Примечание стороны: Нет. Вы не будете. Если значение имеет значение, вы проверяете с помощью ContainsKey, существует ли оно, и извлекаете его, если оно существует. Не пробуй / лови.