我有很多方法非常相似,如下面的代码所示:
public static void ReadFromKeyboard(string label, out int retVal)
{
try
{
Console.Write(label);
retVal = int.Parse(Console.ReadLine());
}
catch (Exception)
{
Console.WriteLine("Please insert int value.");
ReadFromKeyboard(label, out retVal);
}
}
public static void ReadFromKeyboard(string label, out float retVal)
{
try
{
Console.Write(label);
retVal = float.Parse(Console.ReadLine());
}
catch (Exception)
{
Console.WriteLine("Please insert float value.");
ReadFromKeyboard(label, out retVal);
}
}
public static void ReadFromKeyboard(string label, out double retVal)
{
try
{
Console.Write(label);
retVal = double.Parse(Console.ReadLine());
}
catch (Exception)
{
Console.WriteLine("Please insert double value.");
ReadFromKeyboard(label, out retVal);
}
}
另一方面,我不知道我会调用哪个方法。我只会在运行时发现它。
有什么方法可以将这些方法重写为一个名为“ReadFromKeyboard”的方法,该方法根据作为参数传递给它的类型返回 int、float 或 double?
谢谢!
最佳答案
正如其他答案所示,您可以通过各种技术消除重复代码,所有这些技术都很糟糕,您不应该这样做。
特别是,不要试图使用泛型来解决这个“问题”。 泛型适用于代码是泛型的情况。这就是为什么它们被称为泛型!也就是说,代码对每种可能的类型都执行相同的操作。您的示例与通用代码相反;您对少数类型有不同规则,而处理这种情况的方法就是完全按照您已经做过的事情:针对不同的类型实现一种方法规则。
我在引号中说“问题”是因为您在这里实际上没有要解决的问题,所以停止尝试解决它。编写六种类似的短方法对作者或维护者来说不是主要负担。
现在,也就是说,您的代码也没有达到应有的水平,您应该重写它。编写代码的正确方法是:
public static int ReadInteger(string label)
{
while(true)
{
int value;
Console.Write(label);
string read = Console.ReadLine();
bool success = int.TryParse(read, out value);
if (success)
return value;
Console.WriteLine("Please type an integer value.");
}
}
您的原始实现的问题是:
- 不要将异常处理用作主线控制流。如果可以避免异常,则不要捕获异常。这就是 TryParse 的用途。
- 不要将递归用作无限循环。如果你想要一个无限循环,那就是
while(true)
是为了。请记住,C# 默认情况下不是尾递归的! - 不要在不需要的情况下使用 out 参数。方法逻辑上返回一个整数,所以实际上返回一个整数。重命名它,以免与其他读取方法发生冲突。让调用者写
Read<int>
并没有令人信服的好处。超过ReadInteger
,以及避免输出参数的许多引人注目的好处。
关于c# - 太多方法非常相似,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61392772/