C# 如何在get中获取公司状况报表;在c中设置日期时间的属性?
我在上课和约会时间玩。我想检查一个人的年龄,如果他们超过16岁或者没有使用get,set属性。这是课堂考试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
它在主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);
}
}