اكتب النتيجة مع المشغل الشرطي في C#
-
26-09-2019 - |
سؤال
أحاول استخدام المشغل المشروط ، لكنني أتعلق بالنوع الذي تعتقد أنه يجب أن تكون النتيجة.
فيما يلي مثال لقد حرصت على إظهار القضية التي أواجهها:
class Program
{
public static void OutputDateTime(DateTime? datetime)
{
Console.WriteLine(datetime);
}
public static bool IsDateTimeHappy(DateTime datetime)
{
if (DateTime.Compare(datetime, DateTime.Parse("1/1")) == 0)
return true;
return false;
}
static void Main(string[] args)
{
DateTime myDateTime = DateTime.Now;
OutputDateTime(IsDateTimeHappy(myDateTime) ? null : myDateTime);
Console.ReadLine(); ^
} |
} |
// This line has the compile issue ---------------+
على السطر الموضح أعلاه ، أحصل على خطأ التجميع التالي:
لا يمكن تحديد نوع التعبير الشرطي لأنه لا يوجد تحويل ضمني بين "<null>" و "system.dateTime"
أنا مرتبك لأن المعلمة عبارة عن نوع غير قاطع (DateTime؟). لماذا تحتاج إلى التحويل على الإطلاق؟ إذا كان فارغًا ، فاستخدم ذلك ، إذا كان وقت التاريخ ، فاستخدم ذلك.
كنت تحت انطباع أن:
condition ? first_expression : second_expression;
كان هو نفسه:
if (condition)
first_expression;
else
second_expression;
من الواضح أن هذا ليس هو الحال. ما السبب خلف هذا؟
(ملاحظة: أعلم أنه إذا قمت بعمل "myDateTime" ، فسيعمل في الوقت المناسب ، فسوف يعمل. ولكن لماذا تحتاجه؟
كما ذكرت سابقًا ، هذا مثال مفتعل. في المثال الحقيقي "MyDatetime" ، قيمة تعين البيانات التي لا يمكن إجراؤها.)
المحلول
لا يستنتج المترجم نوع نتيجة المشغل الشرطي من استخدام النتيجة ، ولكن من أنواع وسيطاته. يفشل المترجم عندما يرى هذا التعبير لأنه لا يمكنه استنتاج نوع النتيجة:
IsDateTimeHappy(myDateTime) ? null : myDateTime;
حيث null
و DateTime
غير متوافق ، تحتاج إلى إخبار المترجم بما يجب أن يكون عليه النوع. يجب أن يقوم المدلى بالخدعة:
DateTime? x = IsDateTimeHappy(myDateTime) ? (DateTime?)null : myDateTime;
OutputDateTime(x);
الآن لن يواجه المترجم أي مشاكل. يمكنك أيضًا كتابة ما سبق على سطر واحد إذا كنت تفضل (لكنني ربما لن أفعل هذا):
OutputDateTime(IsDateTimeHappy(myDateTime) ? (DateTime?)null : myDateTime);
إريك ليبرت لديه اجابة جيدة هذا أيضًا مناسب هنا ويذهب إلى مزيد من التفاصيل حول كيفية تحديد المحول البرمجي الأنواع.
نصائح أخرى
والسبب هو أن المشغل الثلاثية يتوقع أن يكون كل من المعاملات من نفس النوع. يتم وضع المشغل بأكمله قبل تعيينه لنتيجة (في هذه الحالة تم تمريره إلى وظيفة) ، لذلك لا يمكن للمترجم معرفة نوع النتيجة.
IsDateTimeHappy(myDateTime) ? null : myDateTime
في الحالة أعلاه لا يوجد مسار تحويل بين null
و DateTime
. بمجرد أن تلقي أحدهم DateTime?
, ، يمكن للمترجم تحويل الآخر:
IsDateTimeHappy(myDateTime) ? (DateTime?)null : myDateTime
//OR
IsDateTimeHappy(myDateTime) ? null : (DateTime?)myDateTime
يعمل خط القبضة من الكود أعلاه لأنه يمكن للمترجم تحويله DateTime
ل DateTime?
عبر مشغل تحويل ضمني:
//In Nullable<T>
public static implicit operator T?(T value);
السطر الثاني يعمل بسبب null
يمكن تعيينه ل DateTime?
لأن هذا الأخير هو نوع مرجعي.
التحويل الضمني غير مسموح به من خلال بيان الإرجاع. إذا كان لديك
if (condition)
return first_expression;
else
return second_expression;
ثم تقارن التفاح بالتفاح. وليس لديك أي مشاكل - كما ذكرت.
في حالتك ، يتم تخصيص مساحة كبيرة على المكدس لوقت البيانات - وهو نوع قيمة غير قابل للفرق. لذلك أنت تدلي ببيان لا معنى له للمترجم. إذا قلت ، سأجري لك A
أو أ B
, ، ثم A
و ال B
يجب أن تكون نفس الشيء. في حالتك ، B
لا يمكن أن يكون أبدا A
.
أعتقد أن هذا يتم الرد عليه أيضًا هنا:الأنواع الباطلة والمشغل الثلاثية: لماذا "؟ 10: لاغى؟
أتمنى أن يكون هذا ما تحتاجه. =
ما يقوله المترجم هو:
لو
IsDateTimeHappy(myDateTime)
هوfalse
, ، ثم أحتاج إلى إرجاع قيمة النوعDateTime
يساويmyDateTime
. اذا كانتtrue
, ، ثم أحتاج إلى إرجاع قيمة مساوية لnull
, ، لكنك لم تخبرني ما هو النوع الذي يجب أن يكون!
لهذا السبب فإن إجابة مارك هي الحل. بعد أن تقدم طاقمًا لإخبار المترجم عن نوع القيمة التي سيتم إرجاعها إذا كانت الحالة true
, ، يمكنه التحقق مما إذا كان true
و false
يمكن تحويل قيم الإرجاع إلى (أو من) نفس النوع.
هتاف مارك! ؛-)
بدلاً من null
استعمال default(DateTime?)
ثم كلا الجانبين من الثلاثية سيكون لهما أنواع متوافقة.