Неверное преобразование DateTime
Возможный дубликат:
С# почему can not nullable int присваивается null как значение
Я пытаюсь преобразовать мой читатель [3] объект, который является datetime, равным null, если для форума нет lastPostDate, но он говорит, что Im не пропускает преобразование.
Ошибка:
Тип условного выражения не может быть определен, потому что нет никакого неявного преобразования между <null>
и '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;
}
}
}
Ниже мой объект класса для форума с 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; }
}
}
Ответы
Ответ 1
Возможно, вы захотите сделать это следующим образом:
DateTime? lastPostDate = (DateTime?)(reader.IsDbNull(3) ? null : reader[3]);
Проблема, с которой вы сталкиваетесь, заключается в том, что тернарный оператор хочет иметь живой бросок между левой и правой сторонами. И null нельзя отбрасывать в DateTime.
Обратите внимание на приведенные выше работы, поскольку обе стороны тройки являются объектами. Объект явно отображается в DateTime? который работает: пока читатель [3] на самом деле является датой.
Ответ 2
Убедитесь, что эти два типа nullable DateTime
var lastPostDate = reader[3] == DBNull.Value ?
null :
(DateTime?) Convert.ToDateTime(reader[3]);
- Использование
DateTime?
вместо Nullable<DateTime>
- это временная заставка...
- Используйте лучший отступ? как я это сделал.
Я нашел это прекрасное объяснение в Eric Lippert blog:
В спецификации для оператора ?:
указано следующее:
Второй и третий операнды оператора?: управляют типом условное выражение. Пусть X и Y - типы второго и третьих операндов. Тогда,
-
Если X и Y являются одним и тем же типом, то это тип условного выражение.
-
В противном случае, если между X и Y существует неявное преобразование, но не от Y до X, то Y является типом условного выражения.
-
В противном случае, если неявное преобразование существует от Y до X, но не от X в Y, то X является типом условного выражения.
-
В противном случае, тип выражения не может быть определен, и возникает ошибка времени компиляции.
Компилятор не проверяет, что такое тип, который может "удерживать" эти два типа.
В этом случае:
-
null
и DateTime
не относятся к одному типу.
-
null
не имеет неявного преобразования в DateTime
-
DateTime
не имеет неявного преобразования в null
Таким образом, мы получаем ошибку времени компиляции.
Ответ 3
Передайте нулевой литерал: (DateTime?)null
или (Nullable<DateTime>)null
.
Вы также можете использовать default(DateTime?)
или default(Nullable<DateTime>)
И, как уже отмечали другие ответы, вы также можете применить приведение к значению DateTime, а не к нулевому литералу.
EDIT (адаптированный из моего комментария к ответу Prutswonder):
Дело в том, что условный оператор не рассматривает тип целевой цели назначения, поэтому он будет компилироваться только в том случае, если существует неявное преобразование из типа его второго операнда в тип его третьего операнда или из типа его третьего операнда к типу его второго операнда.
Например, это не будет компилироваться:
bool b = GetSomeBooleanValue();
object o = b ? "Forty-two" : 42;
Приведение второго или третьего операнда к object
, однако, устраняет проблему, потому что существует неявное преобразование из int в объект, а также из строки в объект:
object o = b ? "Forty-two" : (object)42;
или
object o = b ? (object)"Forty-two" : 42;
Ответ 4
Вы можете попробовать это
var lastPostDate = reader[3] == DBNull.Value ?
default(DateTime?):
Convert.ToDateTime(reader[3]);