Как оптимизировать общий метод печати - PullRequest
0 голосов
/ 09 мая 2019

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

private void PrintExample<T>(string fileName, T message)
{
    using (StreamWriter sw = new StreamWriter(fileName, true))
    {
        if (message.GetType() == typeof(string))
        {
            // print something here
        }

        else if (message.GetType() == typeof(SortedList<someClass, string>))
        {
            sw.WriteLine("-------------------------------------------------------------------");
            sw.WriteLine("|           1           |        2        |         3             |");
            sw.WriteLine("-------------------------------------------------------------------");
            foreach (KeyValuePair<someClass, string> kvp in message as SortedList<someClass, string>)
            {
                // print something here
            }
            sw.WriteLine("------------------------------------------------------------------------------------------");
            sw.WriteLine();
        }

        else if (message.GetType() == typeof(Dictionary<int, List<someClass>>))
        {
            sw.WriteLine("-------------------------------------------------------------------");
            sw.WriteLine("|     SOMETHING     |     Name    |          Something2           |");
            sw.WriteLine("-------------------------------------------------------------------");

            foreach (KeyValuePair<int, List<someClass>> kvp in message as Dictionary<int, List<someClass>>)
            {
                foreach (someClass date in kvp.Value)
                {
                    // print something here
                }
                sw.WriteLine("-------------------------------------------------------------------");
            }
            sw.WriteLine();
        }

        else if (message.GetType() == typeof(List<someClass>))
        {
            sw.WriteLine("--------------------------------------------------------------------");
            sw.WriteLine("|     other header     |             other header 7777             |");
            sw.WriteLine("--------------------------------------------------------------------");

            foreach (someClass date in message as List<someClass>)
            {
                // print something here
            }
            sw.WriteLine("----------------------------------------------------");
            sw.WriteLine();
        }
    }
}

Но я полагаю, что это не очень хороший способ делать подобные вещи. Есть ли способ оптимизировать код? Кстати, использование универсального метода не обязательно, просто я реализовал код.

1 Ответ

0 голосов
/ 09 мая 2019

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

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

Вы начинаете с этого:

if (message.GetType() == typeof(string))
  // code to print the string
if (message.GetType() == typeof(SomethingElse))
  // code to print SomethingElse

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

if (message.GetType() == typeof(string))
  PrintString((string)message);
if (message.GetType() == typeof(SomethingElse))
  PrintSomethingElse((SomethingElse)message);

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


Что еще лучше, если нам не нужно проверять и аргументировать, чтобы увидеть, какой это тип. Код за пределами PrintExample<T> уже знает, какой тип он будет передавать методу. Он звонит PrintExample<string>(), PrintExample<SomethingElse>() и т. Д.

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

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

public void Print(string value)

public void Print(SomethingElse value)

С этим еще проще работать. Общий метод позволяет вам вызывать

PrintExample<ThisCouldBeAnything>(thing);

Но что, если ThisCouldBeAnything на самом деле не является типом, который метод может печатать? Если у вас есть разные методы для разных типов, тогда, если у вас есть переменная определенного типа, действительно легко увидеть, существует ли метод для ее печати. Также легко вызвать правильный метод.

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

Если методы печати List<Something> и Dictionary<int, Something> оба должны печатать детали Something, вы можете иметь один PrintSomething метод, который оба они вызывают.


Вот еще кое-что, что нужно учитывать: вы создаете методы, которые принимают разные вещи и пишут строки, которые их описывают. Как есть, ваш класс может писать только в файл. Что если вы хотите большую часть этой функциональности, но не хотите записывать в файл? Что, если вы хотите записать это на консоль или сделать что-то еще с ней?

Может быть, лучше поместить их в отдельный класс или классы, чтобы методы возвращали string или передавали StreamWriter методу или классу. Таким образом, если класс хочет что-то записать в файл, этот класс может использовать класс «Printer» или классы для этого. Но если другой класс хочет сделать что-то еще с выходными данными, он может это сделать.

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...