لماذا تسفر التعدادات غير الملحوظة عن نتائج غريبة؟

StackOverflow https://stackoverflow.com/questions/4026374

  •  26-09-2019
  •  | 
  •  

سؤال

النظر في ما يلي ::

Object box = 5;
int @int = (int)box;  // int = 5
int? nullableInt = box as int?; // nullableInt = 5;
StringComparison @enum = (StringComparison)box; // enum = OrdinalIgnoreCase
StringComparison? nullableEnum = box as StringComparison?; // nullableEnum = null.

2 أشياء ::

  1. لماذا يمكنني إلغاء الابتكار StringComparison؟ أعتقد أن هذا لأنه نوع أساسي Int32 لكن ما زلت أجدها غريبًا.
  2. لماذا nullableEnum هل لديك قيمة فارغة؟

بما أنني أفهم أن إلغاء اللاصطحاب الوحيد الصحيح هو من نوع القيمة المعبأة هو إلى نوعه أو إلى نوع غير مألوف. لو int يمكن أن تلون Enum, ، إذن لماذا لا ينطبق الشيء نفسه على القيم الباطلة؟ وبالمثل ، إذا بدلاً من 5 أنا محاصر StringComparison.OrdinalIgnoreCase, ، سيكون ذلك nullableInt سيكون فارغا ، ولكن nullableEnum لن يكون.

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

المحلول

بالمعنى الدقيق للكلمة ، أعتقد أنه أ علة في تفاصيل تنفيذ وقت التشغيل ، منذ أن تقول C# spec

ينتج عن إلغاء اللاصطناع إلى نوع فارغ القيمة الخالية من النوع الباطل إذا كان المعامل المصدر خاليًا ، أو النتيجة ملفوفة لفصل مثيل الكائن إلى النوع الأساسي من النوع الذي لاغية على خلاف ذلك.

هذا هو ، إذا كان إلغاء التزامن على stringcomparison يعمل ، ثم إلغاء الالتفاف إلى Nullableu003CStringComparison> يجب أن تعمل أيضا. من غير الواضح بعض الشيء ما إذا كان ينبغي أن يعمل كلاهما أو يجب أن يفشل كلاهما. المواصفات تقول ذلك

من أجل تحويل إلغاء التزامن إلى نوع معين من النوع غير القابل للقيمة لتحقيق النجاح في وقت التشغيل ، يجب أن تكون قيمة معامل المصدر إشارة إلى قيمة محاصر لهذا النوع غير القابل للقيمة.

عليك أن تقرر ما إذا كان int محاصر هو قيمة محاصر من نوع stringcomparison لأن النوع الأساسي من stringComparison هو int. تستمر المواصفات إلى القول إنه يتم إلقاء مجموعة غير صالحة إذا كان المربع يحتوي على "كائن غير متوافق". من المؤكد أن INT "متوافق" مع StringComparison ، لأنه يمكنك نسخ البايت الأربعة بأمان من الكومة إلى متغير StringComparison الخاص بك.

نصائح أخرى

عندما تقوم بإلقاء التعداد أو عدد صحيح إلى الكائن ، فإنه لا يزال يحمل معلومات النوع. لذا box is StringComparison سيعود false. ولكن يُسمح له بإلقاء أي تعداد أو int لأي تعداد ، حتى يصرف صريحًا (StringComparison)box يعمل. إنها حالة خاصة للعوامل. Nullable<T>, ، من ناحية أخرى ، هو مجرد فئة معتادة ، لا يتم التعامل مع T بأي طريقة محددة عند إلقاءك أو تحقق. هذا هو السبب في أن هذا الرمز سوف يرمي الاستثناء.

        StringComparison? nullableEnum = (StringComparison?)nullableInt;

1) نعم ، النوع الأساسي من التعداد هو INT وهذا هو السبب في أنه يعمل بهذه الطريقة. أكثر. يمكنك القيام بما يلي:

enum MyEnum
{
    One = 1,
    Two = 2,
}

int i = 3;
MyEnum myEnum = (MyEnum)i; // This works without exceptions.

2) لأن StringComparison? هو في الواقع Nullable<StringComparison> وهو نوع مختلف. و as يتحقق المشغل فقط ما إذا كان الكائن من نفس النوع كما هو محدد في المشغل.

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