Оптимизация c# кода

162
20 ноября 2018, 23:10

Как можно оптимизировать этот код?

int getID<T>(T senderClass, int ID) {
    switch (typeof(T).Name) {
        case "Counter"/* - имя класса*/:
            for (int i = 0; i < countersArray.Count /*list экземпляров класса*/; i++) {
                if (countersArray[i].ID != ID)
                    continue;
                return i;
            }
            break;
        case "Organization":
            for (int i = 0; i < organizationsArray.Count; i++) {
                if (organizationsArray[i].ID != ID)
                    continue;
                return i;
            }
            break;
        case "Representative":
            for (int i = 0; i < representativesArray.Count; i++) {
                if (representativesArray[i].ID != ID)
                    continue;
                return i;
            }
            break;
        case "Service":
            for (int i = 0; i < servicesArray.Count; i++) {
                if (servicesArray[i].ID != ID)
                    continue;
                return i;
            }
            break;
        case "Consumer":
            for (int i = 0; i < consumersArray.Count; i++) {
                if (consumersArray[i].ID != ID)
                    continue;
                return i;
            }
            break;
        case "ServiceByContract":
            for (int i = 0; i < servicesByContract.Count; i++) {
                if (servicesByContract[i].ID != ID)
                    continue;
                return i;
            }
            break;
        case "Contract":
            for (int i = 0; i < contractsArray.Count; i++) {
                if (contractsArray[i].ID != ID)
                    continue;
                return i;
            }
            break;
        case "Flat":
            for (int i = 0; i < flatsArray.Count; i++) {
                if (flatsArray[i].ID != ID)
                    continue;
                return i;
            }
            break;
        case "User":
            for (int i = 0; i < usersArray.Count; i++) {
                if (usersArray[i].ID != ID)
                    continue;
                return i;
            }
            break;
    }
    return 0;
}
Answer 1

Вы можете удалить ваш метод и заменить его на вызовы Array.FindIndex. Например:

var data = Enumerable.Range(0, 10).Select(x => new MyClass() {ID = x}).ToArray();
var ind = Array.FindIndex(data, item=>item.ID == 3);
Console.WriteLine(ind);

Ожидаемый вывод

3

В случае, если вы работаете со списком, а не массивом, то разница небольшая

var data = Enumerable.Range(0, 10).Select(x => new { ID = x }).ToList();
var ind = data.FindIndex(item => item.ID == 3);
Console.WriteLine(ind);

Ожидаемый вывод

3
Answer 2

Судя по использованию свойства Count, все ваши xxxxArray на самом деле List<T>, следовательно для поиска индекса можно использовать его собственный метод FindIndex.

Если ваша задача просто сократить объем кода, то можно воспользоваться возможностями конструкции switch из C#7.

Кроме того, судя по использованию элементов списка, ваш senderClass сам содержит ID и можно избавиться от дополнительного параметра ID в методе.

Как уже написал @tym32167, когда элемент не найден использовать 0 в качестве результата не правильно, т.к. 0 является допустимым индексом любого массива, кроме пустого, следовательно такой ответ будет приводить к ошибкам в дальнейшем. Лучше использовать значение, которое ни когда не может быть допустимым индексом. -1 как раз такое значение и является стандартным для всех поисковых методов в .NET, когда ищется именно индекс элемента.

Все выше описанное будет выглядеть, например, так:

int getID<T>(T senderClass) {
    switch (senderClass) {
        case Counter counter:
            return countersArray.FindIndex(item => item.ID == counter.ID);
        case Organization organization:
            return organizationsArray.FindIndex(item => item.ID == organization.ID);
        case Representative representative:
            return representativesArray.FindIndex(item => item.ID == representative.ID);
        case Service service:
            return servicesArray.FindIndex(item => item.ID == service.ID);
        case Consumer consumer:
            return consumersArray.FindIndex(item => item.ID == consumer.ID);
        case ServiceByContract serviceByContract:
            return servicesByContract.FindIndex(item => item.ID == serviceByContract.ID);
        case Contract contract:
            return contractsArray.FindIndex(item => item.ID == contract.ID);
        case Flat flat:
            return flatsArray.FindIndex(item => item.ID == flat.ID);
        case User user:
            return usersArray.FindIndex(item => item.ID == user.ID);
        default:
            return -1;
    }
}

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

Сразу можно отметить проблему данного метода. Так как на тип-параметр T нет ни каких ограничений, то невозможно понять почему именно элемент не был найден: потому что элемента нет в нужном списке или потому что метод применили к некорректному типу (вызвали с некорректным параметром типа). Это можно поправить возвращая в секции default какое-то другое отрицательное значение, например -2, что добавит информативности, однако простая ошибка: сущность добавили, а метод не исправили - все равно приведет к сложностям в диагностике и отладке.

Стоит так же выделить общий интерфейс у всех сущностей, как минимум явно напрашивается что-то типа:

interfase IHaveID
{
    int ID { get; set: }
}

Раз уж у всех ваших сущностей присутствует ID. За прочие интерфейсы ничего сказать не могу, недостаточно информации.

На правах телепата %):

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

READ ALSO
Имитация файла в потоке из строки

Имитация файла в потоке из строки

Может быть вы можете помочь или натолкнуть на правильное понимание вопроса

158
ACF как вывести метаданные рубрики?

ACF как вывести метаданные рубрики?

У меня на сайте Wordpress установлен плагин ACFЯ создал поля для рубрик и ввел туда данные

159
Выборка и филтрация товара Symfony 4, Elasticseach, MySQL

Выборка и филтрация товара Symfony 4, Elasticseach, MySQL

Всем доброго времени суток! Есть задача: реализовать поисковый фильтр для выборки товара по характеристикам из базы данныхТоваров около...

168
PHP библиотека авторизации через соц. сети

PHP библиотека авторизации через соц. сети

Подскажите пожалуйста библиотеку для авторизации на сайте через социальные сетиКонкретно интересуют Вконтакте, Одноклассники, Facebook

155