2012-02-06 15 views
23

Possible Duplicate:
c# why cant a nullable int be assigned null as a valueanulable DateTime conversión

Im tratando de convertir mi lector [3] que es objeto de fecha y hora a ser nula si no hay lastPostDate para un foro pero no dice Im falta una conversión. 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; 

     } 

    }    
} 

continuación es mi objeto de clase para el Foro con un anulable 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

Consejo: puede usar DateTime? como abreviatura de Nullable , como con todos los tipos Nullable <>. p.ej. ¿En t? ¿Es Nullable , Guid? es Nullable , etc. –

+0

Otro duplicado: http://stackoverflow.com/q/858080/385844 – phoog

+1

¿Puede eliminar el código irrelevante de esta pregunta? puede mantener esta línea solamente: 'Nullable lastPostDate = (reader [3] == DBNull.Value? null: Convert.ToDateTime (reader [3]));' – gdoron

Respuesta

23

Es posible que desee hacerlo de esta manera:

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

El problema que tiene es que el operador ternario quiere un reparto viable entre los lados izquierdo y derecho. Y null no se puede convertir a DateTime.

Tenga en cuenta lo anterior porque ambos lados del ternario son objetos. ¿El objeto está explícitamente lanzado a DateTime? que funciona: siempre que el lector [3] sea, de hecho, una fecha.

25

Asegúrese de que estos dos tipos son nullable DateTime

var lastPostDate = reader[3] == DBNull.Value ? 
             null : 
            (DateTime?) Convert.ToDateTime(reader[3]); 
  • Uso de DateTime? en lugar de Nullable<DateTime> es un ahorro de tiempo ...
  • Usar mejor sangría del? expresión como lo hice.

He encontrado este excelente explicaciones de Eric Lippert blog:

La especificación para las ?: estados operador lo siguiente:

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.

El compilador no comprueba cuál es la tipo que puede "mantener" esos dos tipos.

En este caso:

  • null y DateTime no son del mismo tipo.
  • null no tiene una conversión implícita a DateTime
  • DateTime no tiene una conversión implícita a null

por lo que terminamos con un error de tiempo de compilación.

+1

Gracias por eso. Lo aprecio. trabajado – ONYX

+0

@KDM. Agregué explicaciones del blog Eric Lippert. Espero que te guste. – gdoron

+0

excelentes explicaciones! –

8

Cast the null literal: (DateTime?)null o .

También puede utilizar default(DateTime?) o default(Nullable<DateTime>)

Y, como han dicho en otras respuestas, también se puede aplicar al reparto al valor DateTime en lugar de a la nula literal.

EDITAR (adaptado de mi comentario a la respuesta de Prutswonder):

El punto es que el operador condicional no tiene en cuenta el tipo de su destino de la asignación, por lo que sólo compilará si hay una conversión implícita del tipo de su segundo operando al tipo de su tercer operando, o del tipo de su tercer operando al tipo de su segundo operando.

Por ejemplo, esto no será de compilación:

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

casting ya sea el segundo o tercer operando a object, sin embargo, fija el problema, porque hay una conversión implícita de int a objetar y también de cadena objetar:

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

o

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

No estoy seguro de por qué alguien votó negativamente, ¿es una respuesta correcta por lo que puedo ver? – hvd

5

Haces c una prueba este

var lastPostDate = reader[3] == DBNull.Value ? 
           default(DateTime?): 
           Convert.ToDateTime(reader[3]); 
Cuestiones relacionadas