简体   繁体   中英

How to refactor methods

I have two methods. They're very similar. I've tried use Generics, but it doesn't work with TryParse()

    public static int EnterIntengerNumber()
    {
        while (true)
        {
            Console.Write("Enter an intenger number: ");
            if (int.TryParse(Console.ReadLine(), out int number))
            {
                return number;
            }
            else
            {
                ConsoleError("Incorrect value");
            }
        }
    }


    public static double EnterRealNumber()
    {
        while (true)
        {                
            Console.Write("Enter a number: ");
            if (double.TryParse(Console.ReadLine(), out double number))
            {
                return number;                    
            }
            else
            {
                ConsoleError("Incorrect value");
            }
        }
    }

How can I combine or refactor them?

You can make function, that accepts a delegate with the TryParse parameters and return value as generic. Also you can/will have to make string for asking the correct type. but this can be improved from this example:

    static void Main(string[] args)
    {
        var myDouble = EnterSomething<double>("a double", double.TryParse);
        var myInt = EnterSomething<int>("an interger", int.TryParse);
        Console.WriteLine(myDouble);
        Console.WriteLine(myInt);

        Console.ReadLine();
    }


    public delegate bool TryParseFunction<Tout>(string input, out Tout output);

    public static Tout EnterSomething<Tout>(string typeName, TryParseFunction<Tout> parser)
    {
        while (true)
        {
            Console.Write("Enter " + typeName + " number: ");
            if (parser(Console.ReadLine(), out Tout number))
            {
                return number;
            }
            else
            {
                Console.WriteLine("Incorrect value");
            }
        }
    }

Small additional explanation: the int.TryParse - passing to the EnterSomething is not calling the TryParse. It is actually just "passing" the function so that it can be called in the EnterSomething.

The reason of not using Func<> is that it does not support out variables, see here some example: Func<T> with out parameter

EDIT: I remove the Tin-type parameter, as the input is string anyway.

You can use Convert.ChangeType

Do keep in mind you will end up using boxing so the point of using generics is lost. Though you do end up having less code.

    public static T EnterNumber<T> ()
    {
        while (true)
        {
            Console.Write("Enter an " + typeof(T) + " number: ");
            try
            {
                return (T) Convert.ChangeType(Console.ReadLine(), typeof(T));
            }
            catch (FormatException ex)
            {
                Console.Write("Incorrect format" + ex.Message);
            }
        }
    }

You could try it this way:

public static int EnterIntengerNumber()
{
    return EnterNumber(t => int.TryParse(t, out int v) ? (int?)v : null)
}

public static double EnterRealNumber()
{
    return EnterNumber(t => double.TryParse(t, out double v) ? (double?)v : null)
}

private static T EnterNumber<T>(Func<string, T?> tryParse) where T : struct
{
    while (true)
    {
        Console.Write("Enter a number: ");
        T? result = tryParse(Console.ReadLine());
        if (result.HasValue)
        {
            return result.Value;
        }
        else
        {
            ConsoleError("Incorrect value");
        }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM