C# 如何在get中获取公司状况报表;在c中设置日期时间的属性?

C# 如何在get中获取公司状况报表;在c中设置日期时间的属性?,c#,datetime,get,set,C#,Datetime,Get,Set,我在上课和约会时间玩。我想检查一个人的年龄,如果他们超过16岁或者没有使用get,set属性。这是课堂考试 它在主dob中说,dob;这不是一种方法。如何修复此问题?当您使用get时;设置您不想将Dob作为函数调用,但就像访问类的普通属性一样 Test dob = new Test(new DateTime(2007,12,01)); var myDob = dob.Dob; // myDob is what is return from the get in your get function

我在上课和约会时间玩。我想检查一个人的年龄,如果他们超过16岁或者没有使用get,set属性。这是课堂考试


它在主dob中说,dob;这不是一种方法。如何修复此问题?

当您使用get时;设置您不想将Dob作为函数调用,但就像访问类的普通属性一样

Test dob = new Test(new DateTime(2007,12,01));
var myDob = dob.Dob;
// myDob is what is return from the get in your get function

您没有使用setter

在构造函数中使用它,如下所示:

public Test(DateTime dob)
{
    this.Dob = dob;
}
或者从外部呼叫setter:

dob.Dob = new DateTime(2007,12,01);

这里发生了几件事,有许多思想流派

如果需要进行验证,最好不要在属性设置器中进行验证。有一些很好的理由可以解释为什么你不想在二传中做任何举重动作,如下所示 因为属性似乎是字段,所以它们可能抛出“按设计”异常并不总是显而易见的;而对于方法,程序员被训练去预期和调查异常是否是调用方法的预期结果。 许多.NET基础设施都使用getter,例如WinForms和WPF中的序列化程序和数据绑定—在此类上下文中处理异常可能会很快成为问题。 当您观察或检查对象时,调试器会自动计算属性获取程序。这里的异常可能会使您感到困惑,并减慢调试工作。出于同样的原因,在属性中执行其他昂贵的操作(如访问数据库)也是不可取的。 属性通常用于链接约定:obj.PropA.AnotherProp.YetAnother——使用这种语法,决定在何处插入异常捕获语句就成了问题。 如果要进行验证,抛出ArgumentOutOfRangeException可能是值得的,如果这样做,那么最好是在方法中,将属性设置为私有集,这样脏手指就不会跳过验证 所以我的强迫症改变了你的课程

示例用法

进一步阅读

Dob是类测试的属性,而不是方法

您可以访问Dob,如:

然而,您已经注意到,当您调用测试构造函数时,您的集合逻辑没有启动。我相信这是因为你的年龄检查不正确。调用构造函数时,设置逻辑未正确执行检查的原因是,您正在将_Dob.Year与它的值进行比较。您希望使用value关键字获取尝试设置的值

请参见下面的固定年龄检查示例:

public DateTime Dob
{
    get
    {
        return _Dob;
    }
    set
    {
        if (GetAge(value) < 16)
        {
            Console.WriteLine("You ain't 16!");
        }
        else
        {
            _Dob = value;
        }
    }
}

private int GetAge(DateTime dob)
{
    DateTime today = DateTime.Today;
    int age = today.Year - dob.Year;
    if (dob > today.AddYears(-age))
        age--;

   return age;
}

为了说明代码未编译的原因:您正在调用Dob,就好像它是一个方法一样。事实并非如此;这是一笔财产。您的属性有一个getter和setter;他们在这些情况下被处决:

 Test test = new Test(new DateTime(...));
 DateTime fetched = test.Dob;  // Executes the getter
 test.Dob = new DateTime(...); // Executes the setter
这就是代码不编译的方面

一旦确定,例如使用DateTime dateOfBirth=test.Dob;由于以下代码,您仍然无法验证任何内容:

public Test(DateTime dob)
{
    _Dob = dob;
}
直接分配给字段;它没有使用setter-您正在绕过所有验证

接下来,您的验证将使用_Dob.Year而不是value,这意味着它将验证先前设置的属性值是否正确

其次,验证本身是不正确的,因为它不仅仅是检查年份部分,而不考虑月份和天数。如果我的出生日期是2002年4月22日,我希望!,那么昨天我不会是16岁,但今天我会是。。。您的代码不会发现差异。在下面的代码中,我假设您的16岁以上约束实际上至少有16岁

最后,在控制台中打印错误消息并不是报告错误的惯用方法。使用异常报告错误。在某些情况下,您希望对多个项目分别执行验证并收集所有无效方面,但这超出了本问题的范围

就我个人而言,我认为在属性设置器中进行验证是很好的,假设您需要它可用——另一种设计是将Dob属性设置为只读,并在构造时进行验证。这将回避关于属性设置者是否应该抛出的整个讨论。但是,假设您确实需要一个属性设置器,下面是实现您可能期望的功能的完整代码:

using System;

class Test
{
    private DateTime dateOfBirth;

    public DateTime DateOfBirth
    {
        get => dateOfBirth;
        set
        {
            // Alternative: if (DateTime.Now.AddYears(-16) > value)
            // They behave differently around leap years. Note that
            // currently this is sensitive to the system time zone
            // and the system clock.
            if (value.AddYears(16).Date > DateTime.Today)
            {
                throw new ArgumentOutOfRangeException(
                    nameof(value), "User must be at least 16 years old");
            }
            dateOfBirth = value;
        }
    }

    public Test(DateTime dateOfBirth)
    {
        DateOfBirth = dateOfBirth;
    }
}

class Program
{
    static void Main(string[] args)
    {
        // Note: executed on April 22nd 2018
        Test test = new Test(new DateTime(1970, 1, 1));
        Console.WriteLine(test.DateOfBirth);
        test.DateOfBirth = new DateTime(2002, 4, 22); // Fine: 16th birthday
        Console.WriteLine(test.DateOfBirth);
        test.DateOfBirth = new DateTime(2002, 4, 23);
    }
}

最后一点注意:直接使用系统时钟和系统时区会使代码难以测试。我喜欢将时钟视为一个依赖项,带有一个接口,例如带有系统时钟实现和假时钟实现的IClock。然后,您需要确定您感兴趣的时区,因为这会影响用户的年龄。比如说,我在纽约可能16岁,但在洛杉矶就不行了。不过,这些是相当独立的问题。

谢谢,您的解决方案不会导致任何语法或逻辑错误,但会返回空白。有人说它跳过了conditions@EddieVu:是的,因为你的
构造函数直接分配给字段,然后这里的第二行代码调用getter。没有什么可以调用setter。请注意,这不是一个好的实践。对getter进行这样的检查是意外的行为。如果我在getter上得到一个错误,我假设获取该值是错误的。您通常期望对setter或在本例中对类的构造函数进行这种验证。顺便说一句,我不确定这是否重要,但你的支票不是在检查他们是否超过16岁。如果我是2002年12月出生的,即使我只有15岁,我还是通过了检查。对不起,你使用的是setter,这是正确的。它不起作用的事实是因为你没有使用setter。这是一个很好的答案,也是一个很好的例子,可以为客户提供他们需要的东西,而不是他们想要的东西。你的第一点在我看来很困惑——它说你不应该在setter中进行验证,但随后讨论了调用getter的各种情况。我认为在setter中进行验证是很好的,事实上这样做是很常见的。但我不同意使用单独的方法-这使得在课堂上不经验证就意外设置值变得非常容易。@DaisyShipton正如我所说,有各种各样的思想流派,没有一种解决方案适合所有人,然而,我确实提供了尽可能多的信息。@TheGeneral:但即使我同意不应该在属性设置器中进行验证,我也不同意;尝试将List.Capacity设置为-1例如,我希望看到不同的参数。你的4个要点中有3个是关于何时调用getter的。这些要点并不支持你关于何时调用setter的观点。我认为,如果去掉这些要点,答案至少会更好。@DaisyShipton是的,在许多地方,框架会在属性中进行验证,但是您忽略了要点,并且过于担心它。我认为这是一个很好的经验法则,是一个指导原则,因此,应该由编写代码和审查代码的人来决定。然而,在这种情况下,对于这个用户的问题,我会感到很肮脏,就像我从属性和注释设置向控制台写入任何内容一样。
var test = new Test(new DateTime(2010, 01, 01));
var dob = test.Dob;
public DateTime Dob
{
    get
    {
        return _Dob;
    }
    set
    {
        if (GetAge(value) < 16)
        {
            Console.WriteLine("You ain't 16!");
        }
        else
        {
            _Dob = value;
        }
    }
}

private int GetAge(DateTime dob)
{
    DateTime today = DateTime.Today;
    int age = today.Year - dob.Year;
    if (dob > today.AddYears(-age))
        age--;

   return age;
}
 Test test = new Test(new DateTime(...));
 DateTime fetched = test.Dob;  // Executes the getter
 test.Dob = new DateTime(...); // Executes the setter
public Test(DateTime dob)
{
    _Dob = dob;
}
using System;

class Test
{
    private DateTime dateOfBirth;

    public DateTime DateOfBirth
    {
        get => dateOfBirth;
        set
        {
            // Alternative: if (DateTime.Now.AddYears(-16) > value)
            // They behave differently around leap years. Note that
            // currently this is sensitive to the system time zone
            // and the system clock.
            if (value.AddYears(16).Date > DateTime.Today)
            {
                throw new ArgumentOutOfRangeException(
                    nameof(value), "User must be at least 16 years old");
            }
            dateOfBirth = value;
        }
    }

    public Test(DateTime dateOfBirth)
    {
        DateOfBirth = dateOfBirth;
    }
}

class Program
{
    static void Main(string[] args)
    {
        // Note: executed on April 22nd 2018
        Test test = new Test(new DateTime(1970, 1, 1));
        Console.WriteLine(test.DateOfBirth);
        test.DateOfBirth = new DateTime(2002, 4, 22); // Fine: 16th birthday
        Console.WriteLine(test.DateOfBirth);
        test.DateOfBirth = new DateTime(2002, 4, 23);
    }
}