asignar - datetime nullable to datetime c#
Nullable DateTime conversión (4)
Posible duplicado:
c # por qué no se puede asignar un valor nulo a un valor nulo como un valor
Estoy tratando de convertir el objeto de mi lector [3] que es datetime a ser nulo si no hay lastPostDate para un foro pero dice que no tengo una conversión Error:
El tipo de expresión condicional no se puede determinar porque no hay una conversión implícita entre
<null>
y ''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;
}
}
}
A continuación se muestra mi objeto de clase para el foro con un 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; }
}
}
Asegúrate de que esos dos tipos sean nullable DateTime
var lastPostDate = reader[3] == DBNull.Value ?
null :
(DateTime?) Convert.ToDateTime(reader[3]);
- Uso de
DateTime?
En lugar deNullable<DateTime>
es un ahorro de tiempo ... - Use mejor sangría de la? expresión como lo hice.
He encontrado estas excelentes explicaciones en el blog Eric Lippert:
La especificación para el operador ?:
Establece lo siguiente:
El segundo y tercer operandos del operador?: Controlan el tipo de expresión condicional. Sean X e Y los tipos del segundo y tercer operandos. Entonces,
Si X e Y son del mismo tipo, entonces este es el tipo de la expresión condicional.
De lo contrario, si existe una conversión implícita de X a Y, pero no de Y a X, entonces Y es el tipo de expresión condicional.
De lo contrario, si existe una conversión implícita de Y a X, pero no de X a Y, entonces X es el tipo de expresión condicional.
De lo contrario, no se puede determinar ningún tipo de expresión y se produce un error en tiempo de compilación.
El compilador no comprueba cuál es el tipo que puede "mantener" esos dos tipos.
En este caso:
-
null
yDateTime
no son del mismo tipo. -
null
no tiene una conversión implícita aDateTime
-
DateTime
no tiene una conversión implícita anull
Así que terminamos con un error en tiempo de compilación.
Convierta el literal nulo: (DateTime?)null
(Nullable<DateTime>)null
o (Nullable<DateTime>)null
.
También puede usar el default(DateTime?)
O el default(Nullable<DateTime>)
Y, como han señalado otras respuestas, también puede aplicar la conversión al valor DateTime en lugar de al literal nulo.
EDITAR (adaptado de mi comentario a la respuesta de Prutswonder):
El punto es que el operador condicional no considera el tipo de su objetivo de asignación, por lo que solo 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. Operando al tipo de su segundo operando.
Por ejemplo, esto no compilará:
bool b = GetSomeBooleanValue();
object o = b ? "Forty-two" : 42;
Sin embargo, convertir el segundo o tercer operando en object
, soluciona el problema, porque hay una conversión implícita de int a objeto y también de cadena a objeto:
object o = b ? "Forty-two" : (object)42;
o
object o = b ? (object)"Forty-two" : 42;
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 funciona porque ambos lados de la ternaria son objetos. El objeto se convierte explícitamente a DateTime? que funciona: mientras el lector [3] sea de hecho una fecha.
Puedes probar esto
var lastPostDate = reader[3] == DBNull.Value ?
default(DateTime?):
Convert.ToDateTime(reader[3]);