【问题标题】:This code assigns to the age variable the default value 0此代码为年龄变量分配默认值 0
【发布时间】:2018-12-27 00:00:48
【问题描述】:

我正在尝试在 Student 类中创建属性 Age。我已经编写了下面的代码,但是当我运行它时,值 0 会立即分配给 age 变量。

我希望允许用户从控制台输入信息,但我还需要处理 Age 属性中可能出现的错误。

我在 Student 类中有以下代码:

    private int age;
    public int Age
    {
        get
        {
            return age;
        }
        set
        {
            string age1 = Console.ReadLine();
            try
            {
                int.Parse(age1);
            }

            catch (ArgumentNullException)
            {
                Console.WriteLine("Age was not entered.");
            }
            catch (ArgumentOutOfRangeException)
            {
                if (value < 0 || value > 100)
                {
                    Console.WriteLine("Please enter a valid age!");
                }
                /*else
                {
                    age = value;
                }*/
            }
            age = value;
        }
    }
    public void PrintInformation()
    {
        Console.WriteLine($"Age: {Age} ");

    }

这在 Main 方法中:

        Console.Write("Please enter age: ");
        Console.WriteLine(student.Age);
        student.PrintInformation();

我需要这个输出-> 年龄:(从用户输入的年龄)。我该如何解决这个问题?

【问题讨论】:

  • 你会想要从你的属性设置器中提取大部分逻辑。
  • set 访问器中,起初您不使用隐式参数value 来保存属性设置的值。相反,您考虑string age1 = Console.ReadLine();,并尝试将其解析为int(不获取结果值,并且不使用适用于此场景的TryParse 方法)。最后,您毕竟将支持变量设置为value。你能看出问题吗?
  • 在尝试解决此问题时要问自己两个问题。 a) 为什么不对int.Parse 的返回值做任何事情? b) value 来自哪里?
  • 这看起来像是大学项目分配的高潮。

标签: c# properties output


【解决方案1】:

在 setter 方法中读取用户的输入是一个糟糕的主意。您应该在设置器值之外读取输入,并且在打印之前。 setter 最多应包含实际设置属性值或计算某些内容的逻辑,但应尽可能以最简单的方式编写。

话虽如此,您的代码出了什么问题,实际上您只是在Console.WriteLine(student.Age); 中打印学生的年龄,它甚至没有调用您的Age 属性的setter 方法,而这反过来又是根本不会调用 Console.ReadLine() 来读取用户的输入。

对于Age 属性,您应该按照以下方式进行操作:

public int Age { get; set; }

对于您的输入/输出操作(可能在程序的 Main() 方法中):

string age1 = Console.ReadLine();
try
{
    student.Age = int.Parse(age1);
    if (student.Age < 0 || student.Age > 100)
        Console.WriteLine("Please enter a valid age!");
    else
        Console.WriteLine($"Age: {student.Age} ");

}
catch (FormatException)
{
    Console.WriteLine("Invalid number entered.");
}

【讨论】:

  • 代码不正确。它抛出一个错误:名称'value'在当前上下文中不存在。
  • 对不起。 value 应该是 student.Age
  • ArgumentNullException 不起作用,当年龄超过 100 时,它不会显示消息,而是分配给定的值。所以这也行不通。
  • 这个问题对我来说有点老了,但我想我只是根据您原始帖子的代码编写答案而没有实际测试代码。答案现在有效。如果age1 包含一个空或无效的数字,则会抛出一个FormatException。年龄只能在正确解析后才能测试,因此它应该在解析之后发生,而不是在异常捕获块中。
【解决方案2】:
  1. 想要在属性 getter/setter 中与控制台交互是非常不寻常的。

    • 这也属于Separation of Concerns 的类别。即,与标准输入交互真的是学生生活中的工作吗?如果您将其从控制台应用程序更改为 Web 应用程序或 WPF 应用程序怎么办……您将不得不重新检查所有这些逻辑
  2. 不要使用Parse作为用户输入,使用TryParse如果字符串可以被解析为整数则返回真或假

将数字的字符串表示形式转换为其 32 位有符号 整数等效。一个返回值表示是否操作 成功了。

对于这个应用程序,您可能(并且巧妙地)在控制台应用程序的更高级别的 while 循环中进行验证。

Console.WriteLine("Enter age between 0 and 100");

int age = 0;
while(!int.TryParse(Console.ReadLine(), out  age) || age < 0 || age > 100)
   Console.WriteLine("You had one job, enter a correct age between 0 and 100 (inclusively)");

student.Age = age;

作为第二道防线,你可以做这样的事情(值得商榷)

public int Age
{
   get => _age;
   set
   {
      if (value < 0 )
         throw new InvalidOperationException("Negative aged people are absurd");

      _age = value;
   }
}

注意:有很多方法可以做到这一点,但要点是;使用正确的解析方法;并尽可能保持你的 getter 和 setter 轻。是的,您可以根据自己的需要在其中进行验证并抛出,尽管与其中的控制台交互非常可疑

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-10-13
    • 2011-04-15
    • 1970-01-01
    • 1970-01-01
    • 2019-09-18
    • 2021-06-18
    • 1970-01-01
    • 2015-01-19
    相关资源
    最近更新 更多