努力寻找相同代码行为不同的原因。提供的答案确实可以运行,但是当我从解决方案手册中输入相同的代码时,我得到了ArgumentOutOfRangeException
。我只是看不出我的问题在哪里。
解决方案手册中的代码,类日期:
// Exercise 10.6 Solution: Date.cs
// Date class declaration.
using System;
public class Date
{
private int month; // 1-12
private int day; // 1-31 based on month
private int year; // >0
private static readonly int[] DAYSPERMONTH =
{ 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
// constructor: use property Month to confirm proper value for month;
// use property Day to confirm proper value for day
public Date(int theDay, int theMonth, int theYear )
{
Month = theMonth; // validate month
Year = theYear; // validate year
Day = theDay; // validate day
Console.WriteLine( "Date object constructor for date {0}", this );
} // end Date constructor
// property that gets and sets the year
public int Year
{
get
{
return year;
} // end get
private set
{
year = CheckYear( value );
} // end set
} // end property year
// property that gets and sets the month
public int Month
{
get
{
return month;
} // end get
private set // make writing inaccessible outside the class
{
month = CheckMonth( value );
} // end set
} // end property Month
// property that gets and sets the day
public int Day
{
get
{
return day;
} // end get
private set // make writing inaccessible outside the class
{
day = CheckDay( value );
} // end set
} // end property Day
// increment the day and check if doing so will change the month
public void NextDay()
{
if ( !endOfMonth() )
++Day;
else
{
Day = 1;
NextMonth();
}
} // end method NextDay
// increment the month and check if doing so will change the year
public void NextMonth()
{
if ( Month < 12 )
++Month;
else
{
Month = 1;
++Year;
}
} // end method NextMonth
// return a string of the form month/day/year
public override string ToString()
{
return string.Format($"{Day:D2}/{Month:D2}/{Year}");
} // end method ToString
// utility method to confirm proper year value
private int CheckYear( int testYear )
{
if ( testYear > 0 ) // validate year
return testYear;
else // year is invalid
throw new ArgumentOutOfRangeException(
"year", testYear, "year must greater than 0" );
} // end method CheckYear
// utility method to confirm proper month value
private int CheckMonth( int testMonth )
{
if ( testMonth > 0 && testMonth <= 12 ) // validate month
return testMonth;
else // month is invalid
throw new ArgumentOutOfRangeException(
"month", testMonth, "month must be 1-12" );
} // end method CheckMonth
// utility method to confirm proper day value based on month and year
private int CheckDay( int testDay )
{
// Check if day in range for month
if ( testDay > 0 && testDay <= DAYSPERMONTH[ Month ] )
return testDay;
// Check for leap year
if ( testDay == 29 && leapYear() )
return testDay;
throw new ArgumentOutOfRangeException(
"day", testDay, "day out of range for current month/year" );
} // end method CheckDay
// check for end of month
private bool endOfMonth()
{
if ( leapYear() && Month == 2 && Day == 29 )
return true;
else
return Day == DAYSPERMONTH[ Month ];
} // end method endOfMonth
private bool leapYear()
{
return Month == 2 && ( Year % 400 == 0 ||
( Year % 4 == 0 && Year % 100 != 0 ) );
} // end method leapYear
} // end class Date
解决方案手册中的代码,DateTest类:
// Exercise 10.6 Solution: DateTest
// Application tests Date class with year validation,
// NextDay and NextMonth methods.
using System;
public class DateTest
{
// method Main begins execution of C# application
public static void Main( string[] args )
{
Console.WriteLine( "Checking increment" );
Date testDate = new Date( 18, 9, 1980 );
// test incrementing of day, month and year
for ( int counter = 0; counter < 40; counter++ )
{
testDate.NextDay();
Console.WriteLine( "Incremented Date: {0}",
testDate.ToString() );
}
Console.Read();// end for
} // end Main
} // end class DateTest
我自己复制的代码来自解决方案手册,类Date:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static System.Console;
namespace Ex_10._06
{
public class Date
{
private int day;
private int month;
private int year;
private static readonly int[] DAYSPERMONTH = { 0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
public Date(int theDay, int theMonth, int theYear)
{
Day = theDay;
Month = theMonth;
Year = theYear;
WriteLine($"Date object constructor for date {this}");
}
public int Year
{
get
{
return year;
}
private set
{
year = CheckYear(value);
}
}
public int Month
{
get
{
return month;
}
private set
{
month = CheckMonth(value);
}
}
public int Day
{
get
{
return day;
}
private set
{
day = CheckDay(value);
}
}
public void NextDay()
{
if (!endOfMonth())
++Day;
else
{
Day = 1;
NextMonth();
}
}
public void NextMonth()
{
if (Month < 12)
++Month;
else
{
Month = 1;
++Year;
}
}
public override string ToString()
{
return string.Format("{0}/{1}/{2}", Day, Month, Year);
}
private int CheckYear(int testYear)
{
if (testYear >= 0)
return testYear;
else
throw new ArgumentOutOfRangeException("Year", testYear, "Year must be equal or greater than 0");
}
private int CheckMonth(int testMonth)
{
if (testMonth > 0 && testMonth <= 12)
return testMonth;
else
throw new ArgumentOutOfRangeException("Month", testMonth, "Month must be 1-12");
}
private int CheckDay(int testDay)
{
if (testDay > 0 && testDay <= DAYSPERMONTH[Month])
return testDay;
if (testDay == 29 && leapYear())
return testDay;
throw new ArgumentOutOfRangeException("Day", testDay, "Day out of range for current month/year");
}
private bool endOfMonth()
{
if (leapYear() && Month == 2 && Day == 29)
return true;
else
return Day == DAYSPERMONTH[Month];
}
private bool leapYear()
{
return Month == 2 && (Year % 400 == 0 || (Year % 4 == 0 && Year % 100 != 0));
}
}
}
我自己的代码是从解决方案手册DateTest类中复制的:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using static System.Console;
namespace Ex_10._06
{
public class DateTest
{
public static void Main(string[] args)
{
WriteLine("Checking increment");
Date d1 = new Date(18, 9, 1979);
for (int i = 0; i < 100; i++)
{
d1.NextDay();
WriteLine($"Incremented Date: {d1.ToString()}");
}
Read();
}
}
}
说实话,我还在学习。也许有一些我忽略的东西,但我甚至复制了如何缩进的样式,仍然会产生ArgumentOutOfRangeException,而原始代码确实运行。在此先感谢您的时间。
查看图片调用堆栈: Call Stack
答案 0 :(得分:2)
您遇到的错误是因为您在构造函数中切换了属性赋值的顺序。当你宣布一个新的日期时,你会在其他任何事情之前做CheckDay,这可以判断这一天是否在给定月份有效,但是在指定月份之前完成,这是你的例外。
在原始代码中
[[NSAttributedString alloc] initWithData:[@"<head><meta ... </ruby>" dataUsingEncoding:NSUTF8StringEncoding]
options:@{
NSCharacterEncodingDocumentAttribute : @(NSUTF8StringEncoding),
NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType
}
documentAttributes:NULL
error:NULL];
在你的代码中
Month = theMonth; // validate month
Year = theYear; // validate year
Day = theDay; // validate day
这会导致错误,因为需要在日期之前定义一个月,因为它使用当前月份作为索引来检查数组。
具体来说,在CheckDay()中,运行此代码
Day = theDay;
Month = theMonth;
Year = theYear;
当if (testDay > 0 && testDay <= DAYSPERMONTH[Month])
return testDay;
评估此
Month = null