Nullable DateTime変換

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

Imは私の読者[3]オブジェクトを変換しようとしていますdatetimeは、フォーラムのlastPostDateがない場合はnullになるが、私は変換を見逃していると言います。 エラー:

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

public class Forums
{
    public List 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 forums = new List();
            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 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を持つForumのクラスオブジェクトです。

    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 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 _lastPosteDate = null;
    public Nullable LastPostDate
    {
        get { return _lastPosteDate; }
        set { _lastPosteDate = value; }
    }
    private string _lastPostTitle = "";
    public string LastPostTitle
    {
        get { return _lastPostTitle; }
        set { _lastPostTitle = value; }
    }
}
23
追加された 著者 phoog,
無関係なコードをこの質問に削除してください。この行だけを保持することができます: Nullable lastPostDate =(reader [3] == DBNull.Value?null:Convert.ToDateTime(reader [3]));
追加された 著者 gdoron,
ヒント:DateTimeを使用できますか? Nullable の省略形であり、すべてのNullable <>型と同様です。例えばint? Nullable 、Guidですか? Nullable などです。
追加された 著者 Roy Goode,

4 答え

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 is a time saver...
  • Use better indent of the ? expression like I did.

私はEric Lippert ブログ

?:演算子の仕様では、次のように記述されています。

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.

コンパイラは、これら2つの型を「保持」できる型が何であるかをチェックしません。

この場合:

  • 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

だから我々はコンパイル時のエラーに終わる。

25
追加された
有難うございます。それは有り難いです。働いた
追加された 著者 ONYX,
優れた説明!
追加された 著者 Carlos Liu,
@KDM。私はEric Lippertのブログからexplantionsを追加しました。あなたがそれを好きだと思います。
追加された 著者 gdoron,

次のようにしたいと思うかもしれません:

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

あなたが持っている問題は、三元演算子が左右の間で実行可能なキャストを望んでいるということです。 nullはDateTimeにキャストできません。

三項の両側がオブジェクトであるため、上記の動作に注意してください。オブジェクトは明示的にDateTimeにキャストされますか?リーダ[3]が実際に日付である限り、動作します。

24
追加された

Cast the null literal: (DateTime?)null または (Nullable)null.

You can also use default(DateTime?) または default(Nullable)

また、他の回答に記載されているように、nullリテラルではなく、DateTime値にキャストを適用することもできます。

編集(私のコメントからPrutswonderの答えに適応):

ポイントは、条件付き演算子はその代入対象の型を考慮しないため、2番目のオペランドの型から3番目のオペランドの型への暗黙的な変換がある場合、または3番目の型の型からの暗黙の変換がある場合にのみコンパイルされますオペランドを第2オペランドの型に変換します。

例えば、これはコンパイルされません:

bool b = GetSomeBooleanValue();
object o = b ? "Fまたはty-two" : 42;

しかし、第2または第3オペランドのいずれかを object にキャストすると、intからobjectへ、およびstringからobjectへの暗黙的な変換が行われるため、問題が修正されます。

object o = b ? "Fまたはty-two" : (object)42;

または

object o = b ? (object)"Fまたはty-two" : 42;
8
追加された
なぜ誰かがこれを棄却したのか分かりませんが、私が見る限り正解です。
追加された 著者 hvd,

あなたはこれを試すことができます

var lastPostDate = reader[3] == DBNull.Value ?
                                default(DateTime?): 
                                Convert.ToDateTime(reader[3]);
5
追加された