Вопрос по dictionary, .net, switch-statement – .NET: переключение против словаря для строковых ключей

11

У меня есть ситуация, когда у меня есть бизнес-объект с около 15 свойствами различных типов. Бизнес-объект также должен реализовывать интерфейс, который имеет следующий метод:

object GetFieldValue(string FieldName);

Я вижу 2 способа реализации этого метода:

Используйте оператор switch:

switch ( FieldName )
{
    case "Field1": return this.Field1;
    case "Field2": return this.Field2;
    // etc.
}

Используйте словарь (SortedDictionary или HashTable?):

return this.AllFields[FieldName];

Что будет более эффективным?

Добавлено: Забыл сказать. Этот метод предназначен для отображения элемента в сетке. Сетка будет иметь столбец для каждого из этих свойств. Обычно будут сетки с более чем 1000 элементов в них. Вот почему я беспокоюсь о производительности.

Добавлено 2:

Вот идея: гибридный подход. Создайте статический словарь, в котором ключами будут имена свойств, а значениями - индексы в массиве. Словарь заполняется только один раз, при запуске приложения. Каждый экземпляр объекта имеет массив. Итак, поиск будет выглядеть так:

return this.ValueArray[StaticDictionary[FieldName]];

Алгоритм заполнения словаря может использовать отражение. Затем сами свойства будут реализованы соответствующим образом:

public bool Field1
{
    get
    {
        object o = this.ValueArray[StaticDictionary["Field1"]]; 
        return o == null ? false : (bool)o;
    }
    set
    {
        this.ValueArray[StaticDictionary["Field1"]] = value;
    }
}

Кто-нибудь может увидеть какие-либо проблемы с этим?

Это также может быть сделано на один шаг вперед, и ValueArray / StaticDictionary можно поместить в отдельный универсальный типValueCollection<T>, гдеT указал бы тип для отражения. ValueCollection также будет обрабатывать случай, когда еще не установлено значение. Свойства могут тогда быть написаны просто как:

public bool Field1
{
    get
    {
        return (bool)this.Values["Field1"];
    }
    set
    {
        this.Values["Field1"] = value;
    }
}

И, в конце концов, я снова начинаю удивляться, может ли простой оператор switch быть быстрее и проще в обслуживании ...

Хо, хорошо, это довольно большое, может быть, отражение не очень хороший вариант в вашем случае Fredou
Объект будет отображаться в сетке, которая будет запрашивать свойства. У меня обычно будет около 1000 предметов в такой сетке. Это 15 000 рефлексов. Мне страшно подумать, что произойдет, если каждый из них займет 1 мс. Vilx-
важна производительность в миллисекундах? Fredou
Разве это не должно быть медленнее, чем любой из них? Vilx-

Ваш Ответ

4   ответа
7

вероятно, будет быстрее. Switch будет по существу переведен в хеш-таблицу при использовании строк. Но если вы используете целые числа или что-то подобное, оно будет переведено в таблицу переходов и будет быстрее.

видетьэтот ответ и вопрос для более подробной информации

Лучше всего профилировать и найти наверняка

0

Вы можете создать настроенное сообщение об исключении в разделе по умолчанию, которое может содержать недопустимое значение. В случае словаря вы получаете только исключение KeyNotFoundException, которое не содержит имени ключа.Вы можете обрабатывать нулевые значения. Словарь не может хранить ноль в качестве ключа.
0

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

Позвольте привести пример: допустим, у вас есть следующая реализация:

private string _latestFieldName = string.Empty;
private PropertyInfo _propertyInfo;

object GetFieldValue(string FieldName)
{
  if(FieldName != _latestFieldName)
  {
    _propertyInfo = typeof(yourTypeName).GetProperty(FieldName);
  }
  return _propertyInfo.GetValue(this,null);
}

Если ваш рендеринг сетки отображает строку за один раз с использованием отражения, он должен будет каждый раз получать информацию о недвижимости. Когда вы визуализируете столбец за столбцом, вам нужно будет получать propertyInfo только один раз для каждого свойства, и так как предсказание ветвления будет правильным почти каждый раз, когда вы пропустите очень мало тактов в if. Если у вас уже есть PropertyInfo, и вам не нужно приводить результат вызова к GetValue. использование отражения ОЧЕНЬ близко к использованию метода получения свойства, когда дело касается скорости.

Моя точка зрения, прежде чем вы начнете оптимизировать, используйте профилировщик. (Конечно, если вы не можете изменить сетку, вы не сможете ее оптимизировать)

Нет, я не могу изменить сетку. :) Vilx-
21
switch:      good efficiency, least maintainable
dictionary:  good efficiency, better maintainability
reflection:  least efficient, best maintainability

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

Я не говорю, что отражение - это ваш единственный выбор, просто оно позволяет вам добавлять / удалять и переименовывать свойства по мере необходимости, и не нужно синхронизировать оператор switch или словарь.

Я склонен считать, что когнитивные издержки рефлексии делают его несколько менее поддерживаемым, чем подход словаря таблицы диспетчеризации. Хотя это может быть просто потому, что я не часто использую отражение. :) Greg D
Хм ... хорошо ... хорошо ... Vilx-
Словарь более эффективен, чем оператор switch? Я не ожидал этого, не могли бы вы уточнить? Bubblewrap
Отражение это дьявол Faruz
@Rune, я могу гарантировать, что словарь быстрее, чем отражение. Существуют хеш-таблицы и словари в области компьютерных наук, потому что они могут обеспечить более высокую производительность для извлечения данных, чем большинство других структур данных. Принимая во внимание, что существует отражение, чтобы обеспечить обнаруживаемость типов во время выполнения, а не по соображениям производительности. Но не верьте мне на слово, попробуйте сравнение в качестве эксперимента. Ash

Похожие вопросы