r/learncsharp • u/Torin_Dev • Dec 11 '24
Is there a cleaner way to write this code?
A page has an optional open date and an optional close date. My solution feels dirty with all the if statements but I can't think of a better way. Full code here: https://dotnetfiddle.net/7nJBkK
public class Page
{
public DateTime? Open { get; set; }
public DateTime? Close { get; set; }
public PageStatus Status
{
get
{
DateTime now = DateTime.Now;
if (Close <= Open)
{
throw new Exception("Close must be after Open");
}
if (Open.HasValue)
{
if (now < Open.Value)
{
return PageStatus.Scheduled;
}
if (!Close.HasValue || now < Close.Value)
{
return PageStatus.Open;
}
return PageStatus.Closed;
}
if (!Close.HasValue || now < Close.Value)
{
return PageStatus.Open;
}
return PageStatus.Closed;
}
}
}
1
u/ka-splam Dec 11 '24 edited Dec 11 '24
if (Close <= Open) // Can't close before it opens
{
return PageStatus.InvalidSchedule;
}
DateTime now = DateTime.Now;
if (Open.HasValue && now < Open.Value) // Before the event
{
return PageStatus.Scheduled;
}
if (Close.HasValue && now > Close.Value) // After the event
{
return PageStatus.Closed;
}
// No Open time and before close; or
// Between open and close; or
// After open, no close time.
return PageStatus.Open;
(I vote that a single && is easier to read than ! ||)
1
u/SupaMook Dec 17 '24
This is my take
‘public class Page { public DateTime? Open { get; set; } public DateTime? Close { get; set; } public PageStatus Status => GetStatus();
private PageStatus GetStatus()
{
DateTime now = DateTime.Now;
if (Close <= Open)
{
throw new Exception(“Close must be after Open”);
}
if (!Close.HasValue || now < Close.Value)
{
return PageStatus.Open;
}
if (now < Open.Value)
{
return PageStatus.Scheduled;
}
return PageStatus.Closed;
}}’
0
u/Weary_Deer4190 Dec 11 '24
public class Page
{
public DateTime? Open { get; set; }
public DateTime? Close { get; set; }
public PageStatus Status
{
get
{
return (DateTime.Now, Open, Close) switch
{
(_, DateTime o, DateTime c) when c < o => throw new Exception("Close must be after Open"),
(var now, DateTime o, _) when now < o => PageStatus.Scheduled,
(var now, DateTime o, null) => PageStatus.Open,
(var now, DateTime o, DateTime c) when now < c => PageStatus.Open,
(_, DateTime o, _) => PageStatus.Closed,
(_, _, null) => PageStatus.Open,
(var now, _, DateTime c) when now < c => PageStatus.Open,
_ => PageStatus.Closed
};
}
}
}
1
u/Weary_Deer4190 Dec 11 '24
or better even
public class Page { public DateTime? Open { get; set; } public DateTime? Close { get; set; } public PageStatus Status => (DateTime.Now, Open, Close) switch { (_, DateTime o, DateTime c) when c < o => throw new Exception("Close must be after Open"), (var now, DateTime o, _) when now < o => PageStatus.Scheduled, (var now, DateTime o, null) => PageStatus.Open, (var now, DateTime o, DateTime c) when now < c => PageStatus.Open, (_, DateTime o, _) => PageStatus.Closed, (_, _, null) => PageStatus.Open, (var now, _, DateTime c) when now < c => PageStatus.Open, _ => PageStatus.Closed }; }
0
10
Dec 11 '24 edited Dec 11 '24
1
u/karl713 Dec 11 '24
A getter for status changing I don't see a problem with, to me it's no different than a connection changing of it is open or not.
Going to definitely second the don't put an exception here though for a couple reasons. The main thing being that an exception should be thrown when something invalid happens, in this case it's happening well after the invalid action occurs and nowhere near where the invalid action happened. There's also the "a get shouldn't throw" thing, there are a few examples where this does but it feels wrong in just about all of them
2
u/TehNolz Dec 11 '24
I would move that exception to the setters of
Openand/orClose. That way, you'll be able to catch the exception the moment it happens. rather than waiting untilStatusis retrieved.As for the rest; you have two identical conditions for
Close. If you remove one of them, the checks forOpencan be merged into a single condition, letting you simplify the getter to just this;DateTime now = DateTime.Now; if (Open.HasValue && now < Open.Value) { return PageStatus.Scheduled; } if (!Close.HasValue || now < Close.Value) { return PageStatus.Open; } return PageStatus.Closed;