Почему не выполняется функция? - PullRequest
0 голосов
/ 18 октября 2019

Я работаю над созданием приложения, такого как терминал вывода (Unix) или приглашение командной строки (Windows). Я создал словарь, который имеет несколько ключевых слов для функции. Но когда я называю эти ключевые слова, ничего не делается. Моя программа называется Control Line Control (или CLC). И я использую .NET Core, который предназначен для всех работающих программ (Linux, macOS и Windows).

Я не знаю, что именно попробовать. Функция есть функция. Он должен быть выполнен, когда я его вызываю.

using System;
using System.Collections.Generic;
using System.Threading;
using System.IO;

namespace CLC
{
    class Program
    {    
        static DirectoryInfo maindirectory;
        static Dictionary<string, string> keyaction;
        static string value;

        static void WritePathOfWorkingDirectory(DirectoryInfo directory)
        {
            if (directory != null)
            {
                Console.Write("{0}:", directory.FullName);
            }
            else
            {

            }
        }

        static void ProcessAnswer(string[] array)
        {
            string action = array.GetValue(0).ToString();
            value = array.GetValue(1).ToString();
            string c = keyaction[action];

            Console.Write(c);
        }

        static string ListFiles()
        {
            foreach(var file in maindirectory.GetFiles())
            {
                Console.WriteLine(file.Name);
            }

            return "ok";
        }

        static string ListDirectories()
        {
            foreach(var directory in maindirectory.GetDirectories())
            {
                Console.WriteLine(directory);
            }

            return "ok";
        }

        static void MainProgramm()
        {
            WritePathOfWorkingDirectory(maindirectory);

            string data = Console.ReadLine();
            var arry = data.Split(' ');

            ProcessAnswer(arry);

            Thread repeat = new Thread(MainProgramm);
            repeat.Start();
        }

        static void Main(string[] args)
        {
            maindirectory = new DirectoryInfo("C:/Users");

            keyaction = new Dictionary<string, string>();
            keyaction.Add("lf", ListFiles());
            keyaction.Add("ld", ListDirectories());

            Console.Clear();

            maindirectory = new DirectoryInfo("C:/Users");

            Thread thread = new Thread(new ThreadStart(MainProgramm));
            thread.Start();
        }
    }
}

Ожидаемый результат - выполнить то, что говорит ключ: например, если я наберу ld (список каталогов), должна быть выполнена функция списка каталогов. Но я ничего не понимаю! Программа просто повторяется.

Ответы [ 2 ]

0 голосов
/ 18 октября 2019

Основная проблема в том, что вы сохраняете значение string в словаре, а не в самой функции, поэтому, когда вы добавляете функции, вы добавляете их немедленное возвращаемое значение (прежде чем вы когда-либо предложите пользователю ввести данные).

Вместо этого значение словаря должно быть Func<string>, которое вы можете затем .Invoke по требованию.

Кроме того, казалось, что вы не проверяли запись пользователя. Мы можем использовать TryGetValue для ввода пользователя, чтобы убедиться, что он ввел правильную команду (если она существует в словаре). Если это не так, мы можем сказать им, что их ввод неверен.

Кроме того, при доступе к значениям массива вы должны сначала убедиться, что индекс, к которому вы обращаетесь, действителен (если пользователь вводит только одну команду,как "lf" без значения, то вы не можете получить доступ к индексу массива [1], потому что он не существует.

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

Попробуйте этот код с изменениями:

public class Program
{
    private static DirectoryInfo _maindirectory = new DirectoryInfo("C:\\Users");

    private static Dictionary<string, Func<string>> _keyaction =
        new Dictionary<string, Func<string>>
        {
            {"lf", ListFiles},
            {"ld", ListDirectories},
            {"cd", ChangeDirectory},
            {"exit", Exit}
        };

    private static string _value;

    private static void DisplayPrompt(FileSystemInfo directory)
    {
        Console.Write($"{directory?.FullName ?? "[cmd]"}: ");
    }

    private static void ProcessAnswer(IReadOnlyList<string> array)
    {
        var action = array.Count > 0 ? array[0] : string.Empty;
        _value = array.Count > 1 ? array[1] : null;
        Func<string> method;
        _keyaction.TryGetValue(action, out method);

        if (method == null)
        {
            WriteError($"Unknown command: {action}");
        }
        else
        {
            Console.WriteLine(_keyaction[action].Invoke());
        }
    }

    private static string ListFiles()
    {
        var dir = Directory.Exists(_value) ? new DirectoryInfo(_value) : _maindirectory;

        foreach (var file in dir.GetFiles())
        {
            Console.WriteLine(file.Name);
        }

        return "ok";
    }

    private static string ListDirectories()
    {
        var dir = Directory.Exists(_value) ? new DirectoryInfo(_value) : _maindirectory;

        foreach (var directory in dir.GetDirectories())
        {
            Console.WriteLine(directory);
        }

        return "ok";
    }

    private static string ChangeDirectory()
    {
        if (Directory.Exists(_value))
        {
            _maindirectory = new DirectoryInfo(_value);
        }
        else if (Directory.Exists(Path.Combine(_maindirectory.FullName, _value)))
        {
            _maindirectory = new DirectoryInfo(
                Path.Combine(_maindirectory.FullName, _value));
        }
        else
        {
            WriteError("Directory not found.");
        }

        return "ok";
    }

    private static void WriteError(string message)
    {
        Console.ForegroundColor = ConsoleColor.Red;
        Console.WriteLine(message);
        Console.ResetColor();
    }

    private static string Exit()
    {
        Environment.Exit(0);
        return "ok";
    }

    private static void Main()
    {
        while (true)
        {
            DisplayPrompt(_maindirectory);
            ProcessAnswer(Console.ReadLine()?.Split(' '));
        }
    }
}
0 голосов
/ 18 октября 2019

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

Ваш метод Main должен выглядеть следующим образом:

static void Main(string[] args)
    {
        maindirectory = new DirectoryInfo("C:/Users");

        keyaction = new Dictionary<string, Func<string>>(); // changed this to an Func instead of a string

        keyaction.Add("lf", ListFiles); // notice I removed the parentheses here

        keyaction.Add("ld", ListDirectories); // and here

        Console.Clear();

        maindirectory = new DirectoryInfo("C:/Users");

        Thread thread = new Thread(new ThreadStart(MainProgramm));

        thread.Start();
    }

, а ключевая операция должна быть объявлена ​​следующим образом:

static Dictionary<string, Func<string>> keyaction; // a Func<string> is a function that returns a string and takes no arguments

Затем в вашем методе ProcessAnswer вам необходимо вызвать функцию через ссылку, указанную в Словаре:

 static void ProcessAnswer(string[] array)
    {
        string action = array.GetValue(0).ToString();

        value = array.GetValue(1).ToString();

        string c = keyaction[action](); // calling the referenced funtion

        Console.Write(c);

    }

Это должно дать ожидаемый результат.

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

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