سؤال

لقد بحثت كثيرا ولكن لم أجد حلا.كيف تتعامل مع DateTime الذي يجب أن يكون قادرًا على احتواء قيمة غير مهيأة (أي ما يعادل قيمة خالية)؟لدي فئة قد تحتوي على قيمة خاصية DateTime أم لا.كنت أفكر في تهيئة مالك الخاصية إلى DateTime.MinValue، والذي يمكن بعد ذلك التحقق منه بسهولة.أعتقد أن هذا سؤال شائع جدًا، كيف يمكنك أن تفعل ذلك؟

هل كانت مفيدة؟

المحلول

لDateTimes العادية، إذا لم يكن لتهيئة لهم على الإطلاق بعد ذلك سوف تطابق DateTime.MinValue، لأنه هو نوع القيمة بدلا من نوع مرجع.

ويمكنك أيضا استخدام التاريخ والوقت قيم الفارغة، مثل هذا:

DateTime? MyNullableDate;

وأو شكل أطول:

Nullable<DateTime> MyNullableDate;

وأخيرا، هناك بنيت في الطريق إلى مرجع تقصير من أي نوع. هذا يعود null لأنواع المرجعية، ولكن على سبيل المثال لدينا التاريخ والوقت فإنه سيعود نفس DateTime.MinValue:

default(DateTime)

نصائح أخرى

إذا كنت تستخدم الصافي 2.0 (أو الأحدث)، يمكنك استخدام نوع قيم الفارغة:

DateTime? dt = null;

أو

Nullable<DateTime> dt = null;

وبعد ذلك في وقت لاحق:

dt = new DateTime();

ويمكنك التحقق من القيمة مع:

if (dt.HasValue)
{
  // Do something with dt.Value
}

أو يمكنك استخدامه مثل:

DateTime dt2 = dt ?? DateTime.MinValue;

ويمكنك قراءة المزيد هنا:
http://msdn.microsoft.com/en-us/library/b3h38hb0.aspx

والتاريخ والوقت؟ MyDateTime {الحصول؛ مجموعة؛}

MyDateTime = (dr["f1"] == DBNull.Value) ? (DateTime?)null : ((DateTime)dr["f1"]);

وبعد الطريقة التي يعمل بها، وكذلك

myClass.PublishDate = toPublish ? DateTime.Now : (DateTime?)null;

تجدر الإشارة إلى أن PublishDate الملكية يجب أن يكون التاريخ والوقت؟

فما استقاموا لكم فاستقيموا النظر في استخدام أنواع nullable .

وDateTime? myDate بدلا من DateTime myDate.

ويمكنك استخدام فئة قيم الفارغة.

DateTime? date = new DateTime?();

ويمكنك استخدام التاريخ والوقت قيم الفارغة لذلك.

Nullable<DateTime> myDateTime;

وأو نفس الشيء مكتوبة مثل هذا:

DateTime? myDateTime;

وأنا دائما ضبط الوقت إلى DateTime.MinValue. بهذه الطريقة وأنا لا تحصل على أي NullErrorException ويمكنني مقارنتها إلى تاريخ أعرف لم يتم تعيين.

وتجدر الإشارة إلى أنه، في حين لا يمكن DateTime متغير null، فإنه لا يزال يمكن مقارنة null دون خطأ المترجم:

DateTime date;
...
if(date == null) // <-- will never be 'true'
  ...

فقط كن حذرًا - عند استخدام Nullable، من الواضح أنه لم يعد كائنًا "نقيًا" للتاريخ والوقت، وبالتالي لا يمكنك الوصول إلى أعضاء DateTime مباشرة.سأحاول أن أشرح.

باستخدام Nullable<> فإنك تقوم بشكل أساسي بتغليف DateTime في حاوية (شكرًا لك على الأدوية العامة) والتي تكون خالية - ومن الواضح أن الغرض منها.تحتوي هذه الحاوية على خصائصها الخاصة التي يمكنك الاتصال بها والتي ستوفر الوصول إلى كائن DateTime المذكور أعلاه؛بعد استخدام الخاصية الصحيحة - في هذه الحالة Nullable.Value - يمكنك بعد ذلك الوصول إلى أعضاء DateTime القياسيين والخصائص وما إلى ذلك.

إذن - تتبادر الآن إلى الذهن مسألة أفضل طريقة للوصول إلى كائن DateTime.هناك عدة طرق، الرقم 1 هو الأفضل على الإطلاق والرقم 2 هو "لماذا يا صاح".

  1. باستخدام خاصية Nullable.Value،

    DateTime date = myNullableObject.Value.ToUniversalTime(); //Works

    DateTime date = myNullableObject.ToUniversalTime(); //Not a datetime object, fails

  2. تحويل الكائن الفارغ إلى وقت التاريخ باستخدام Convert.ToDateTime()،

    DateTime date = Convert.ToDateTime(myNullableObject).ToUniversalTime(); //works but why...

على الرغم من أن الإجابة موثقة جيدًا في هذه المرحلة، أعتقد أن استخدام Nullable ربما كان يستحق النشر عنه.آسف إذا كنت لا توافق.

يحرر:تمت إزالة الخيار الثالث لأنه كان محددًا بشكل مفرط ويعتمد على الحالة.

على الرغم من أن الجميع قد أعطاك الإجابة بالفعل، إلا أنني سأذكر طريقة تجعل من السهل تمرير التاريخ والوقت إلى إحدى الوظائف

[خطأ: لا يمكن تحويل system.datetime؟إلى النظام.التاريخ والوقت]

DateTime? dt = null;
DateTime dte = Convert.ToDateTime(dt);

يمكنك الآن تمرير dte داخل الوظيفة دون أي مشاكل.

إذا كنت، في بعض الأحيان، وتتوقع لاغية هل يمكن استخدام شيء من هذا القبيل:

var orderResults = Repository.GetOrders(id, (DateTime?)model.DateFrom, (DateTime?)model.DateTo)

في الخاص بك مستودع استخدام التاريخ والوقت، لاغية قادرة.

public Orders[] GetOrders(string id, DateTime? dateFrom, DateTime? dateTo){...}

وكان لي نفس المشكلة كما كان لي لإعطاء فارغة كمعلمة للالتاريخ والوقت أثناء أداء اختبار وحدة الرميات عملت ArgumentNullException.It في حالتي باستخدام الخيار التالي:

Assert.Throws<ArgumentNullException>(()=>sut.StartingDate = DateTime.Parse(null));

نظرًا لطبيعة نوع بيانات التاريخ/الوقت، لا يمكن أن يحتوي على ملف null القيمة، أييجب أن يحتوي على قيمة، ولا يمكن أن يكون فارغًا أو لا يحتوي على أي شيء.إذا قمت بوضع علامة على متغير التاريخ/الوقت كـ nullable عندها فقط يمكنك تعيين قيمة فارغة لها.لذا فإن ما تتطلع إلى القيام به هو أحد أمرين (قد يكون هناك المزيد ولكن لا يمكنني التفكير إلا في اثنين):

  • قم بتعيين الحد الأدنى لقيمة التاريخ/الوقت للمتغير الخاص بك إذا لم يكن لديك قيمة له.يمكنك أيضًا تعيين الحد الأقصى لقيمة التاريخ/الوقت - بأي طريقة تناسبك.فقط تأكد من أنك متسق على مستوى الموقع عند التحقق من قيم التاريخ/الوقت.اتخاذ قرار بشأن استخدام min أو max والتشبث به.

  • قم بتمييز متغير التاريخ/الوقت الخاص بك كـ nullable.بهذه الطريقة يمكنك ضبط متغير التاريخ/الوقت على null إذا لم يكن لديك متغير لذلك.

اسمحوا لي أن أوضح نقطتي الأولى باستخدام مثال.ال DateTime لا يمكن تعيين نوع المتغير على قيمة فارغة، فهو يحتاج إلى قيمة، وفي هذه الحالة سأقوم بتعيينه على قيمة DateTimeالحد الأدنى لقيمة إذا لم يكن هناك قيمة.

السيناريو الخاص بي هو أن لدي BlogPost فصل.يحتوي على العديد من الحقول/الخصائص المختلفة ولكني اخترت استخدام اثنين فقط لهذا المثال. DatePublished هو الوقت الذي تم فيه نشر المنشور على موقع الويب ويجب أن يحتوي على قيمة تاريخ/وقت. DateModified هو عندما يتم تعديل المنشور، لذلك ليس من الضروري أن يحتوي على قيمة، ولكن يمكن أن يحتوي على قيمة.

public class BlogPost : Entity
{
     public DateTime DateModified { get; set; }

     public DateTime DatePublished { get; set; }
}

استخدام ADO.NET للحصول على البيانات من قاعدة البيانات (عيّن DateTime.MinValue ليس هناك قيمة ):

BlogPost blogPost = new BlogPost();
blogPost.DateModified = sqlDataReader.IsDBNull(0) ? DateTime.MinValue : sqlDataReader.GetFieldValue<DateTime>(0);
blogPost.DatePublished = sqlDataReader.GetFieldValue<DateTime>(1);

يمكنك إنجاز نقطتي الثانية عن طريق وضع علامة على DateModified الحقل كما nullable.الآن يمكنك ضبطه على null إذا لم يكن هناك قيمة لذلك:

public DateTime? DateModified { get; set; }

استخدام ADO.NET للحصول على البيانات من قاعدة البيانات، سيبدو الأمر مختلفًا بعض الشيء عن الطريقة التي تم بها أعلاه (تعيين null بدلاً من DateTime.MinValue):

BlogPost blogPost = new BlogPost();
blogPost.DateModified = sqlDataReader.IsDBNull(0) ? (DateTime?)null : sqlDataReader.GetFieldValue<DateTime>(0);
blogPost.DatePublished = sqlDataReader.GetFieldValue<DateTime>(1);

آمل أن يساعد هذا في إزالة أي لبس.نظرًا لأن ردي كان بعد حوالي 8 سنوات، فمن المحتمل أن تكون الآن مبرمجًا خبيرًا في لغة C# :)

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top