Подтвердить что ты не робот

Неверное преобразование 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; }
    }
}
4b9b3361

Ответ 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]);