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; }
}
}
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.
Make sure those two types are nullable DateTime
var lastPostDate = reader[3] == DBNull.Value ?
null :
(DateTime?) Convert.ToDateTime(reader[3]);
DateTime?
instead of Nullable<DateTime>
is a time saver...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,
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.
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;
You can try this
var lastPostDate = reader[3] == DBNull.Value ?
default(DateTime?):
Convert.ToDateTime(reader[3]);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With