可能性のある複製:
c#null可能intに値としてnullを割り当てることができない理由
フォーラムのlastPostDateがない場合、datetimeであるreader [3]オブジェクトをnullに変換しようとしていますが、Im missing in conversionと表示されます。エラー:
<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; }
}
}
あなたはこのようにしたいかもしれません:
DateTime? lastPostDate = (DateTime?)(reader.IsDbNull(3) ? null : reader[3]);
あなたが持っている問題は、三項演算子が左と右の間の実行可能なキャストを望んでいるということです。また、nullをDateTimeにキャストすることはできません。
三項の両側がオブジェクトであるため、上記の動作に注意してください。オブジェクトは明示的にDateTimeにキャストされますか?動作します:reader [3]が実際に日付である限り。
これらの2つのタイプがnullable DateTime
であることを確認してください
var lastPostDate = reader[3] == DBNull.Value ?
null :
(DateTime?) Convert.ToDateTime(reader[3]);
DateTime?
の代わりにNullable<DateTime>
を使用すると、時間を節約できます...Eric Lippertでこの優れた説明を見つけました blog :
?:
演算子の仕様では、次のことを説明しています。
?:演算子の2番目と3番目のオペランドは、条件式のタイプを制御します。 XおよびYを第2および第3オペランドのタイプとします。その後、
XとYが同じタイプの場合、これは条件式のタイプです。
そうではなく、XからYへの暗黙的な変換が存在し、YからXへの変換が存在しない場合、Yは条件式のタイプです。
そうではなく、YからXへの暗黙的な変換が存在し、XからYへの変換が存在しない場合、Xは条件式のタイプです。
そうでない場合、式のタイプを判別できず、コンパイル時エラーが発生します。
コンパイラは、これらの2つの型を「保持」できる型をチェックしません。
この場合:
null
とDateTime
は同じ型ではありません。null
には、DateTime
への暗黙的な変換はありませんDateTime
には、null
への暗黙的な変換はありませんそのため、コンパイル時エラーが発生します。
Nullリテラルをキャストします:_(DateTime?)null
_または_(Nullable<DateTime>)null
_。
default(DateTime?)
またはdefault(Nullable<DateTime>)
を使用することもできます
また、他の回答で指摘されているように、nullリテラルではなくDateTime値にキャストを適用することもできます。
編集(私のコメントからPrutswonderの答えに適応):
ポイントは、条件演算子が割り当てターゲットのタイプを考慮しないため、その第2オペランドのタイプから第3オペランドのタイプ、またはその第3オペランドのタイプへの暗黙的な変換がある場合にのみコンパイルされます第2オペランドの型のオペランド。
たとえば、これはコンパイルされません。
_bool b = GetSomeBooleanValue();
object o = b ? "Forty-two" : 42;
_
ただし、2番目または3番目のオペランドをobject
にキャストすると、intからオブジェクトへの暗黙的な変換、および文字列からオブジェクトへの暗黙的な変換があるため、問題が修正されます。
_object o = b ? "Forty-two" : (object)42;
_
または
_object o = b ? (object)"Forty-two" : 42;
_
これを試すことができます
var lastPostDate = reader[3] == DBNull.Value ?
default(DateTime?):
Convert.ToDateTime(reader[3]);