7
\$\begingroup\$
(cn.PublishEnd == null || cn.PublishEnd < DateTime.Now)

vs

(cn.PublishEnd ?? DateTime.MinValue < DateTime.Now)

Which is more readable? I'm inclined towards the second form, but something tells me I'm wrong.

Context:

namespace Damnation.Website.Main.Business.Extensions
{
 public static class CommunityNews
 {
 public static IEnumerable<DAL.CommunityNews> Published(this ObjectSet<DAL.CommunityNews> table)
 {
 return table.Where(cn => cn.PublishStart > DateTime.Now && DateTime.Now > (cn.PublishEnd ?? DateTime.MinValue)).OrderByDescending(cn => cn.PublishStart);
 }
 }
}

Types

DateTime PublishStart
DateTime? PublishEnd
200_success
146k22 gold badges190 silver badges479 bronze badges
asked Aug 21, 2011 at 15:57
\$\endgroup\$
2
  • \$\begingroup\$ In light of seeing Ivan's answer, I think we'll need a bit more context like, what's that actual type of cn.PublishEnd? If it happened to be of type bool? (very odd), then that would invalidate my answer and would need clarification. Is this going to be a part of a conditional and you use the value somewhere? Other things will change as well in that case. \$\endgroup\$ Commented Aug 21, 2011 at 18:45
  • \$\begingroup\$ It's DateTime?, I'll update with the full snippet. \$\endgroup\$ Commented Aug 21, 2011 at 18:50

3 Answers 3

4
\$\begingroup\$

As for me, the first form is more readable because it clearly describe the condition. It's easy to read and understand. The second form is a little confusing. The first thought I had was: What is the DateTime.Zero? Is this a default value for PublishEnd? If yes then why not to use the DateTime.MinValue? Maybe it's not a default value and I get it wrong somewhere? Of course these thoughts took only seconds but nevertheless. In general I think that ?? should be used to return the default value with expected type. The default value of the PublishEnd should be of DateTime type. But the second form distorts the meaning of ?? and returns bool type instead, and it’s confusing.

Edited: If you want to read is like you said: "if now is greater than (end date or earliest date)" then you should write it like:

(DateTime.Now > cn.PublishEnd ?? DateTime.MinValue)

And this, third form is better than first and second.

answered Aug 21, 2011 at 18:21
\$\endgroup\$
3
  • \$\begingroup\$ it's DateTime.MinValue, I mistyped it. I find it easy to read as "if now is greater than (end date or earliest date)" \$\endgroup\$ Commented Aug 21, 2011 at 18:24
  • \$\begingroup\$ Yes, this part is easy to read, but for me it's confusing because it is not plainly connected to PablishEnd. It's connected to PablishEnd by means of operator that has specific purpose. Once again - it's only my opinion. I prefere plain code. \$\endgroup\$ Commented Aug 21, 2011 at 18:36
  • \$\begingroup\$ Hmm, I didn't realize there wasn't a Zero property of Datetime. Hopefully he intended to use the .NET DateTime and not some custom class, it'd be bad form to name a type the same as one in the System namespace. Also good point at the end, I forgot that the ?? operator has lower precedence than comparison operators. But the intent is clear, any decent IDE would help correct that rather quickly. \$\endgroup\$ Commented Aug 21, 2011 at 18:38
3
\$\begingroup\$

Within a conditional, it would depend largely on the type of the object. In general, I'd favor the first form, particularly if it is a non-string reference type that doesn't offer a nice default value. Otherwise if it was a string or nullable structure, I would prefer the second.

I'd be very careful instantiating new objects only for doing a comparisons like this. It's rather wasteful, especially if you have many comparisons and the object isn't very cheap to instantiate since it's being thrown away.

In this case, it is a nullable (DateTime? apparently) so it would be cleanest IMHO using the second.

answered Aug 21, 2011 at 16:22
\$\endgroup\$
1
\$\begingroup\$

Usualy I solve problems like this with introducing a class DateTimeRange which has a method Contains(DateTime date).

In your case I would rewrite the conditional statement and put it into the CommunityNews class

public class CommunityNews
{
 public bool IsPublished(DateTime checkingDate)
 {
 if (this.PublishStart <= checkingDate)
 {
 return false;
 }
 return this.PublishEnd.HasValue
 ? checkingDate < this.PublishEnd.Value
 : true;
 }
}

Then your search method would become as clear as possible:

 public static IEnumerable<DAL.CommunityNews> Published(this ObjectSet<DAL.CommunityNews> table)
 {
 return table.Where(cn => cn.IsPublished(DateTime.Now)).OrderByDescending(cn => cn.PublishStart);
 }

P.S. In general I would consider using cn.PublishEnd ?? DateTime.MinValue < DateTime.Now in a check statement as a bad practice, because to me ?? is more about return and not about checking.

answered Aug 22, 2011 at 6:39
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.