Nullable DateTime conversion

114,995

Solution 1

You might want to do it like this:

DateTime? lastPostDate =  (DateTime?)(reader.IsDbNull(3) ? null : reader[3]); 

The problem you are having is that the ternary operator wants a viable cast between the left and right sides. And null can't be cast to DateTime.

Note the above works because both sides of the ternary are object's. The object is explicitly cast to DateTime? which works: as long as reader[3] is in fact a date.

Solution 2

Make sure those two types are nullable DateTime

var lastPostDate = reader[3] == DBNull.Value ?
                                        null : 
                                   (DateTime?) Convert.ToDateTime(reader[3]);
  • Usage of DateTime? instead of Nullable<DateTime> is a time saver...
  • Use better indent of the ? expression like I did.

I have found this excellent explanations in Eric Lippert blog:

The specification for the ?: operator states the following:

The second and third operands of the ?: operator control the type of the conditional expression. Let X and Y be the types of the second and third operands. Then,

  • If X and Y are the same type, then this is the type of the conditional expression.

  • Otherwise, if an implicit conversion exists from X to Y, but not from Y to X, then Y is the type of the conditional expression.

  • Otherwise, if an implicit conversion exists from Y to X, but not from X to Y, then X is the type of the conditional expression.

  • Otherwise, no expression type can be determined, and a compile-time error occurs.

The compiler doesn't check what is the type that can "hold" those two types.

In this case:

  • null and DateTime aren't the same type.
  • null doesn't have an implicit conversion to DateTime
  • DateTime doesn't have an implicit conversion to null

So we end up with a compile-time error.

Solution 3

Cast the null literal: (DateTime?)null or (Nullable<DateTime>)null.

You can also use default(DateTime?) or default(Nullable<DateTime>)

And, as other answers have noted, you can also apply the cast to the DateTime value rather than to the null literal.

EDIT (adapted from my comment to Prutswonder's answer):

The point is that the conditional operator does not consider the type of its assignment target, so it will only compile if there is an implicit conversion from the type of its second operand to the type of its third operand, or from the type of its third operand to the type of its second operand.

For example, this won't compile:

bool b = GetSomeBooleanValue();
object o = b ? "Forty-two" : 42;

Casting either the second or third operand to object, however, fixes the problem, because there is an implicit conversion from int to object and also from string to object:

object o = b ? "Forty-two" : (object)42;

or

object o = b ? (object)"Forty-two" : 42;

Solution 4

You can try this

var lastPostDate = reader[3] == DBNull.Value ?
                                default(DateTime?): 
                                Convert.ToDateTime(reader[3]);
Share:
114,995
ONYX
Author by

ONYX

Updated on January 22, 2020

Comments

  • ONYX
    ONYX over 4 years

    Possible Duplicate:
    c# why cant a nullable int be assigned null as a value

    Im trying to convert my reader[3] object which is datetime to be null if there is no lastPostDate for a Forum but it says Im missing a conversion. Error:

    Type of conditional expression cannot be determined because there is no implicit conversion between <null> and 'System.DateTime'

    public class Forums
    {
        public List<Forum> GetForums()
        {
            using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["CMS"].ConnectionString))
            {
                conn.Open();
                SqlCommand cmd = new SqlCommand("sproc_Forums_GetForums", conn);
                cmd.CommandType = CommandType.StoredProcedure;
                SqlDataReader reader = cmd.ExecuteReader(CommandBehavior.Default);
    
                List<Forum> forums = new List<Forum>();
                while (reader.Read())
                {
                    var title = reader[6].ToString();
                    var threadCount = (int)reader[5];
                    var lastPostTitle = reader[4].ToString();
                    // below is where im having a problem
                    Nullable<DateTime> lastPostDate = (reader[3] == DBNull.Value ? null : Convert.ToDateTime(reader[3])); 
                    var lastPostBy = reader[2].ToString();
                    var forumGroup = reader[1].ToString();
                    var description = reader[0].ToString();
    
                    Forum forum = new Forum(0, "",DateTime.Now,
                        reader["Title"].ToString(),description,
                        0,false,"","",DateTime.Now,true,
                        forumGroup, (int)threadCount, lastPostBy,
                        lastPostDate, lastPostTitle);
                    forums.Add(forum);/**/
    
                }
                return forums;
    
            }
    
        }            
    }
    

    Below is my class object for Forum with a Nullable lastPostDate

        public class Forum
    {
        public Forum(int forumID, string addedBy, DateTime addedDate, string title, string description, int parentID, bool moderated,
            string imageUrl, string updatedBy, DateTime? updatedDate, bool active, string forumGroup, int threadCount, string lastPostBy,
            Nullable<DateTime> lastPostDate, string lastPostTitle)
        {
            this.ForumID = forumID;
            this.AddedBy = addedBy;
            this.AddedDate = addedDate;
            this.Title = title;
            this.Description = description;
            this.ParentID = parentID;
            this.Moderated = moderated;
            this.ImageUrl = imageUrl;
            this.UpdatedBy = updatedBy;
            this.UpdatedDate = updatedDate;
            this.Active = active;
            this.ForumGroup = forumGroup;
            this.ThreadCount = threadCount;
            this.LastPostBy = lastPostBy;
            this.LastPostDate = lastPostDate;
            this.LastPostTitle = lastPostTitle;
        }
    
        private int _forumID;
        public int ForumID
        {
            get { return _forumID; }
            set { _forumID = value; }
        }
        private string _addedBy;
        public string AddedBy
        {
            get { return _addedBy; }
            set { _addedBy = value; }
        }
        private DateTime _addedDate = DateTime.Now;
        public DateTime AddedDate
        {
            get { return _addedDate; }
            set { _addedDate = value; }
        }
        private string _title = "";
        public string Title
        {
            get { return _title; }
            set { _title = value; }
        }
        private string _description = "";
        public string Description
        {
            get { return _description; }
            set { _description = value; }
        }
        private int _parentID = 0;
        public int ParentID
        {
            get { return _parentID; }
            set { _parentID = value; }
        }
        private bool _moderated = false;
        public bool Moderated
        {
            get { return _moderated; }
            set { _moderated = value; }
        }
        private string _imageUrl = "";
        public string ImageUrl
        {
            get { return _imageUrl; }
            set { _imageUrl = value; }
        }
        private string _updatedBy = "";
        public string UpdatedBy
        {
            get { return _updatedBy; }
            set { _updatedBy = value; }
        }
        private DateTime? _updatedDate = null;
        public DateTime? UpdatedDate
        {
            get { return _updatedDate; }
            set { _updatedDate = value; }
        }
        private bool _active = false;
        public bool Active
        {
            get { return _active; }
            set { _active = value; }
        }
        private string _forumGroup = "";
        public string ForumGroup
        {
            get { return _forumGroup; }
            set { _forumGroup = value; }
        }
        private int _threadCount = 0;
        public int ThreadCount
        {
            get { return _threadCount; }
            set { _threadCount = value; }
        }
        private string _lastPostBy = "";
        public string LastPostBy
        {
            get { return _lastPostBy; }
            set { _lastPostBy = value; }
        }
        private Nullable<DateTime> _lastPosteDate = null;
        public Nullable<DateTime> LastPostDate
        {
            get { return _lastPosteDate; }
            set { _lastPosteDate = value; }
        }
        private string _lastPostTitle = "";
        public string LastPostTitle
        {
            get { return _lastPostTitle; }
            set { _lastPostTitle = value; }
        }
    }
    
  • ONYX
    ONYX about 12 years
    thankyou for that. I appreciate it. worked
  • Admin
    Admin about 12 years
    I'm not sure why someone downvoted this, it's a correct answer as far as I can see?
  • gdoron is supporting Monica
    gdoron is supporting Monica about 12 years
    @KDM. I added explantions from Eric Lippert blog. Hope you will like it.
  • Malcolm Johnson-Brown
    Malcolm Johnson-Brown about 8 years
    excellent explainations!