2012-02-06 41 views
23

Possible Duplicate:
c# why cant a nullable int be assigned null as a valueNullable DateTime chuyển đổi

Im cố gắng để chuyển đổi đầu đọc của tôi [3] đối tượng đó là datetime để được null nếu không có lastPostDate cho một diễn đàn nhưng nó nói Im thiếu một chuyển đổi. Lỗi:

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; 

     } 

    }    
} 

Dưới đây là đối tượng lớp học của tôi cho diễn đàn với một 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; } 
    } 
} 
+2

Mẹo: bạn có thể sử dụng DateTime? như viết tắt của Nullable , giống như tất cả các loại . ví dụ. int? là Nullable , Guid? là Nullable , v.v. –

+0

Một bản sao khác: http://stackoverflow.com/q/858080/385844 – phoog

+1

Bạn có thể vui lòng xóa mã không có liên quan cho câu hỏi này không? bạn chỉ có thể giữ dòng này: 'Nullable lastPostDate = (reader [3] == DBNull.Value? null: Convert.ToDateTime (reader [3]));' – gdoron

Trả lời

23

Bạn có thể muốn làm điều đó như thế này:

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

Vấn đề bạn đang gặp là các nhà điều hành ternary muốn có một dàn diễn viên khả thi giữa bên trái và phải. Và null không thể được cast vào DateTime.

Lưu ý các tác phẩm trên vì cả hai mặt của bộ ba đều là đối tượng. Đối tượng được đúc một cách rõ ràng với DateTime? hoạt động: miễn là người đọc [3] thực ra là một ngày tháng.

25

Hãy chắc chắn rằng hai loại là nullable DateTime

var lastPostDate = reader[3] == DBNull.Value ? 
             null : 
            (DateTime?) Convert.ToDateTime(reader[3]); 
  • Sử dụng DateTime? thay vì Nullable<DateTime> là trình tiết kiệm thời gian ...
  • Sử dụng thụt lề tốt hơn? biểu hiện như tôi đã làm.

Tôi đã tìm thấy lời giải thích này xuất sắc trong Eric Lippert blog:

Các đặc điểm kỹ thuật cho ?: bang điều hành như sau:

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.

Trình biên dịch không kiểm tra là những gì loại có thể "giữ" hai loại đó.

Trong trường hợp này:

  • nullDateTime không cùng loại.
  • null không có một chuyển đổi ngầm để DateTime
  • DateTime không có một chuyển đổi ngầm để null

Vì vậy, chúng tôi kết thúc với một lỗi thời gian biên dịch.

+1

thankyou for that. Tôi đánh giá cao nó. đã làm việc – ONYX

+0

@KDM. Tôi đã thêm các lời giải thích từ blog của Eric Lippert. Hy vọng bạn sẽ thích nó. – gdoron

+0

giải thích tuyệt vời! –

8

Truyền trống: (DateTime?)null hoặc (Nullable<DateTime>)null.

Bạn cũng có thể sử dụng default(DateTime?) hoặc default(Nullable<DateTime>)

Và, như câu trả lời khác đã lưu ý, bạn cũng có thể áp dụng các diễn viên với giá trị DateTime hơn là vô giá trị văn chương.

EDIT (chuyển thể từ nhận xét của tôi để trả lời Prutswonder của):

Vấn đề là các nhà điều hành có điều kiện không xem xét các loại mục tiêu nhiệm vụ của nó, vì vậy nó sẽ chỉ biên dịch nếu có một chuyển đổi ngầm từ các loại của toán hạng thứ hai của nó cho loại toán hạng thứ ba của nó, hoặc từ kiểu toán hạng thứ ba của nó tới kiểu toán hạng thứ hai của nó.

Ví dụ, điều này sẽ không biên dịch:

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

Đúc một trong hai toán hạng thứ hai hoặc thứ ba để object Tuy nhiên, sửa chữa vấn đề, bởi vì có một chuyển đổi ngầm từ int để phản đối và cũng từ chuỗi phản đối:

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

hoặc

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

Tôi không chắc tại sao một người nào đó đã downvoted điều này, đó là một câu trả lời đúng như tôi thấy? – hvd

5

Bạn c một thử này

var lastPostDate = reader[3] == DBNull.Value ? 
           default(DateTime?): 
           Convert.ToDateTime(reader[3]); 
Các vấn đề liên quan