На что заменить словарь Dictionary<string,object> чтобы избавится от Boxing (C# netcore2.2)

112
02 ноября 2021, 11:00

Достался проект на поддержку, и после решения насущных проблем, пришло время рефакторинга. В одном из основных методов происходит Boxing, этот метод крутится на бекграунде для многих потоков (по экземпляру на поток, без concurrency).

имею метод для замены подстрок по шаблону.

 public static (string resultStr, Dictionary<string,object> resultInsearts) InsertByTemplate(string template, Dictionary<string,object> insearts, string pattern = @"\{(.*?)(:.+?)?\}")
 {
    string Evaluator(Match match)
    {           
       // В insearts по ключу находится значение для замены и возвращается.
        return res;
    }
    var result = Regex.Replace(template, pattern, Evaluator);
 }

В передаваемом словаре insearts содержатся все варианты вставок (около 200 значений) Возвращаемый в кортеже словарь resultInsearts содержит только РЕАЛЬНО вставленные значения. Наиболее используемые типы в cловаре это string, int, DateTime. Т.е. Boxing struct->object происходит часто и при формировании словаря insearts и еще при формировании resultInsearts.

для тестов быстренько заменил словарь на

public class IndependentInserts
{
    #region field
    private readonly Dictionary<string, string> _strDict = new Dictionary<string, string>();
    private readonly Dictionary<string, int> _intDict= new Dictionary<string, int>();
    private readonly Dictionary<string, DateTime> _dateTimeDict  = new Dictionary<string, DateTime>();
    #endregion

    #region Methode
    public bool TryAddValue(string key, int value)
    {
        return _intDict.TryAdd(key, value);
    }
    public bool TryAddValue(string key, string value)
    {
        return _strDict.TryAdd(key, value);
    }
    public bool TryAddValue(string key, DateTime value)
    {
        return _dateTimeDict.TryAdd(key, value);
    }
    public bool TryGetValue(string key, out int value)
    {
        return _intDict.TryGetValue(key, out value);
    }
    public bool TryGetValue(string key, out string value)
    {
        return _strDict.TryGetValue(key, out value);
    }
    public bool TryGetValue(string key, out DateTime value)
    {
        return _dateTimeDict.TryGetValue(key, out value);
    }

    public Dictionary<string, object> Map2BoxeDictionary() //Вызывается редко по запросу пользователя
    {
        var boxeDictionary = new Dictionary<string, object>();
        foreach (var (key, value) in _strDict)
        {
            boxeDictionary[key] = value;
        }
        foreach (var (key, value) in _intDict)
        {
            boxeDictionary[key] = value;
        }
        foreach (var (key, value) in _dateTimeDict)
        {
            boxeDictionary[key] = value;
        }
        return boxeDictionary;
    }
    #endregion
}

public static (string resultStr, IndependentInserts resultInsearts) InsertByTemplate(string template, IndependentInserts insearts, string pattern = @"\{(.*?)(:.+?)?\}")
{
    var resultInsearts = new IndependentInserts(); 
    string Evaluator(Match match)
    {
        string res = null;
        var key = match.Groups[1].Value;
        if (inserts.TryGetValue(key, out string strVal))                 //обработка string значений
        {
        }
        else
        if (inserts.TryGetValue(key, out DateTime dateTimeVal))          //обработка DateTime значений
        {
        }
        else    
        if (inserts.TryGetValue(key, out int intVal))                    //обработка int значений
        {
        }
        else
        if (key.Contains("rowNumber"))                                  //обработка служебных значений
        {
        }
        else
        {
            res = match.Value;
        }
        return res;
    }
    var result = Regex.Replace(template, pattern, Evaluator);
    return (result, resultInsearts);
}

С добавлением элементов все хорошо, TryAddValue вызовет нужный метод по перегрузке. А вот TryGetValue нужно вызывать для каждого типа и проверять в каком же словаре находится подставляемое значение.

Хотел обсудить как бы кто поступил для замены Dictionary?

Пояснения к коду: для вызова метода InsertByTemplate внешний код создает словарь Dictionary<string,object> insearts. Где ключ это строка под замену, а value это значение замены. value это object - и в него помешается как ссылочный тип string, так и структуры int, DateTime. Алгоритм метода InsertByTemplate: это поиск в строке паттерна (через regex) и замена найденной подстроки на значение из словаря.

READ ALSO
перевести из 7 php на 5

перевести из 7 php на 5

есть запись в массиве (7 php)

94
Регулярное выражение не дает добавлять товар в корзину

Регулярное выражение не дает добавлять товар в корзину

Всем приветЕсть регулярка, которая проверяет наименование товара и отправляет его в корзину

87
Открытие файла по ссылке html

Открытие файла по ссылке html

Я вывожу путь к файлу из базы данных

243
Изменение записей в базе данных [закрыт]

Изменение записей в базе данных [закрыт]

Хотите улучшить этот вопрос? Обновите вопрос так, чтобы он вписывался в тематику Stack Overflow на русском

99