我需要根据他的年龄找到某个人的sun-sign
。
例如,
Capricorn December 22 – January 20
Aquarius January 21 – February 18
Pisces February 19 – March 19
Aries March 20 – April 19
Taurus April 20 – May 20
Gemini May 21 – June 20
Cancer June 21 – July 22
Leo July 23 – August 22
Virgo August 23 – September 22
Libra September 23 – October 22
Scorpio October 23 – November 21
Sagittarius November 22 – December 21
我写了这段代码,
public enum Months
{
January = 1, February, March, April, May, June, July, August, September, October, November, December,
}
var person = new Person(name:"mady", age:20, dateTime: new DateTime(2011,09,16));
if (person.DOB.Month == (int)Months.December)
{
if (person.DOB.Day >= 22)
return "Capricorn";
else
return "Sagittarius";
} ...
....
....
....
IF
语句会持续增长,如果明天名单增长,可能会成为一场噩梦。
有找到Sunsign的优雅方式吗? .NET中的Enumerable
或Range
似乎不适合这种情况,或者这是编写代码的唯一方法吗?
答案 0 :(得分:6)
创建一个StarSign类:
class StarSign
{
public readonly string Name;
public readonly DateTime StartDate;
public readonly DateTime EndDate;
public bool Contains(DateTime date);
}
将所有星标添加到StarSigns集合中。然后对于任何给定的DateTime日期(人的)做
foreach (var sign in StarSigns)
{
if (sign.Contains(date))
{
Console.WriteLine("I am a: " + sign.Name);
break;
}
}
编辑,回复您的评论:
包含功能可以轻松比较日期,只需确保忽略年份:
public bool Contains(DateTime date)
{
DateTime startNoYear = new DateTime(1904, StartDate.Month, StartDate.Day);
DateTime endNoYear = new DateTime(1904, EndDate.Month, EndDate.Day);
DateTime dateNoYear = new DateTime(1904, date.Month, date.Day);
return dateNoYear >= startNoYear && dateNoYear <= endNoYear;
}
所以,是的,如果你有很多StarSigns,这将影响性能。 Normaly你只会有12个,而且既然你知道你正在处理一个封闭的套装,你就可以这样做。
在优化方面,您还需要存储startNoYear和endNoYear,而不是每次运行Contains时都计算它们。在构造函数中计算它们;我只是在方法中这样做,所以它更容易理解。更快的是直接处理DateTime属性并避免完全创建新的DateTime对象。就这个例子而言,我选择简化优于优化。
答案 1 :(得分:3)
请注意,您可以比较日期:
if (new DateTime(2012, 1, 1) < new DateTime(2012, 2, 1)) ...
因此,我建议
然后只使用日期比较:
DateTime dob = new DateTime(1904, person.DOB.Month, person.DOB.Day);
if (dob >= new DateTime(1904, 12, 21))
return "Aquarius";
else if (dob >= new DateTime(1904, 11, 22))
return "Sagittarius";
else if (dob >= new DateTime(1904, 10, 23))
return "Scorpio";
...
else
return "Aquarius";
一个明显的改进是创建一个List<Tuple<DateTime, String>>
并迭代它。但是,由于日期不太可能在未来一百年内发生变化,因此在if
条件下对其进行硬编码可能就足够了。
答案 2 :(得分:1)
您可以使用switch语句
switch (person.DOB.Month)
{
.....
case 12:
if (day >= 22) return "Capricorn"; else return "Sagittarius";
break;
.......
}
答案 3 :(得分:0)
你可以建立一个太阳标志的小字典,它将太阳标志的名称作为关键字,并将它的时间跨度作为值。时间跨度是第一次到最后一次。 然后有一个标准时间函数来判断人员DOB是否在时间范围内。 Mayb你需要去除出生年份,但这应该很容易。
最后,您可以使用linq:
var sunsigns as Dictionary<string, TimeSpan>();
// adding sun-signs here
var sunsign = (from s in sunsigns where (methodToTellIfItsinRange(s)) select s).first();
答案 4 :(得分:0)
linq很好..只需使用你的清单...... 看看这个
public class sing
{
public string singName {
get { return _singName; }
set { _singName = value; }
}
private string _singName;
public DateTime singStart {
get { return _singStart; }
set { _singStart = value; }
}
private DateTime _singStart;
public DateTime singEnd {
get { return _singEnd; }
set { _singEnd = value; }
}
private DateTime _singEnd;
public void findSing(System.DateTime usersDate)
{
List<sing> ListOfSings = new List<sing>();
sing scorpio = new sing();
System.DateTime startD = new System.DateTime(1910, 10, 23);
System.DateTime endD = new System.DateTime(1910, 11, 21);
scorpio.singName = "scorpio";
scorpio.singStart = startD;
scorpio.singEnd = endD;
ListOfSings.Add(scorpio);
//' ....etc all the others
dynamic hismonth = usersDate.Month;
dynamic hisDay = usersDate.Day;
System.DateTime fixedDate = new System.DateTime(1910, hismonth, hisDay);
dynamic q = (from i in ListOfSings where i.singStart >= fixedDate && i.singEnd <= fixedDatei).ToList;
MessageBox.Show("your sing is: " + q.FirstOrDefault.singName);
}
}
答案 5 :(得分:0)
DavidBožjak的答案是一个很好的选择。
我认为课程可以是抽象的,并为每个标志实施。 此外,StartDate,EndDate和日期传递参数需要忽略年份。 我这样做了:
public abstract class StarSign
{
public readonly string Name;
public readonly DateTime StartDate;
public readonly DateTime EndDate;
protected StarSign(string name, DateTime startDate, DateTime endDate)
{
Name = name;
StartDate = startDate;
EndDate = endDate;
}
public virtual bool Contains(DateTime date)
{
date = new DateTime(1, date.Month, date.Year);
return date >= StartDate && date <= EndDate;
}
}
public class AquariusStarSign : StarSign
{
public AquariusStarSign()
: base("Aquarius", new DateTime(1, 1, 21), new DateTime(1, 2, 18))
{
}
}
public class CapricornStarSign : StarSign
{
public CapricornStarSign()
: base("Capricorn", new DateTime(1, 12, 21), new DateTime(1, 1, 20))
{
}
public override bool Contains(DateTime date)
{
if (date.Month == StartDate.Month)
return date.Day >= StartDate.Day;
if (date.Month == EndDate.Month)
return date.Day <= EndDate.Day;
return false;
}
}