سؤال

أنا استخدم int على سبيل المثال، ولكن هذا ينطبق على أي نوع قيمة في .Net

في .Net 1، قد يؤدي ما يلي إلى استثناء برنامج التحويل البرمجي:

int i = SomeFunctionThatReturnsInt();

if( i == null ) //compiler exception here

الآن (في .Net 2 أو 3.5) انتهى هذا الاستثناء.

أنا أعرف لماذا هذا:

int? j = null; //nullable int

if( i == j )   //this shouldn't throw an exception

المشكلة هي أنه بسبب int? هو لاغية و int الآن لديه يلقي ضمنا ل int?.بناء الجملة أعلاه هو سحر المترجم.حقا نحن نفعل:

Nullable<int> j = null; //nullable int

//compiler is smart enough to do this
if( (Nullable<int>) i == j)   

//and not this
if( i == (int) j)

والآن، عندما نفعل ذلك i == null نحن نحصل:

if( (Nullable<int>) i == null )

بالنظر إلى أن C# تقوم بمنطق المترجم لحساب هذا على أي حال، فلماذا لا يكون ذكيًا بما يكفي لعدم القيام بذلك عند التعامل مع القيم المطلقة مثل null?

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

المحلول

لا أعتقد أن هذه مشكلة مترجم في حد ذاته;القيمة الصحيحة لا تكون فارغة أبدًا، لكن فكرة مساواتها ليست غير صالحة؛إنها دالة صالحة تُرجع خطأً دائمًا.والمجمع يعلم؛الرمز

bool oneIsNull = 1 == null;

يجمع، ولكن يعطي تحذير مترجم: The result of the expression is always 'false' since a value of type 'int' is never equal to 'null' of type '<null>'.

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

نصائح أخرى

غريب ...تجميع هذا باستخدام VS2008، واستهداف .NET 3.5:

static int F()
{
    return 42;
}

static void Main(string[] args)
{
    int i = F();

    if (i == null)
    {
    }
}

أحصل على تحذير مترجم

warning CS0472: The result of the expression is always 'false' since a value of type 'int' is never equal to 'null' of type 'int?'

ويولد IL التالي ...والذي من المفترض أن يقوم JIT بتحسينه بعيدًا

L_0001: call int32 ConsoleApplication1.Program::F()
L_0006: stloc.0 
L_0007: ldc.i4.0 
L_0008: ldc.i4.0 
L_0009: ceq 
L_000b: stloc.1 
L_000c: br.s L_000e

هل يمكنك نشر مقتطف الكود؟

لا يزال المترجم يُصدر تحذيرًا عند مقارنة النوع غير الفارغ بالنوع الخالي، وهذا هو ما ينبغي أن يكون عليه الأمر تمامًا.ربما يكون مستوى التحذير الخاص بك منخفضًا جدًا أو تم تغيير هذا في الإصدارات الأخيرة (لقد فعلت ذلك فقط في .net 3.5).

قدم إطار العمل 2.0 نوع القيمة الخالية.على الرغم من أن الثابت الحرفي "1" لا يمكن أن يكون فارغًا أبدًا، إلا أنه يمكن الآن تحويل نوعه الأساسي (int) إلى نوع int قابل للتحرير.أعتقد أن المترجم لم يعد بإمكانه افتراض أن أنواع int ليست فارغة، حتى عندما تكون ثابتة حرفية.أحصل على تحذير عند تجميع 2.0:

تحذير 1: نتيجة التعبير تكون دائمًا "خطأ" نظرًا لأن القيمة من النوع "int" لا تساوي أبدًا "خالية" من النوع "int؟"

التحذير جديد (3.5 على ما أعتقد) - الخطأ هو نفسه كما لو كنت قد فعلت ذلك 1 == 2, ، وهو أمر ذكي بما يكفي لاكتشافه على أنه غير صحيح أبدًا.

أظن أنه مع التحسينات الكاملة 3.5 سيتم تجريد البيان بالكامل، لأنه ذكي جدًا مع عدم وجود تقييمات حقيقية أبدًا.

بينما قد أريد 1==2 للتجميع (لإيقاف تشغيل كتلة دالة أثناء اختبار شيء آخر على سبيل المثال) لا أريد 1==null ل.

يجب أن يكون خطأ في وقت الترجمة، لأن الأنواع غير متوافقة (أنواع القيمة لا يمكن أن تكون فارغة أبدًا).ومن المحزن أن الأمر ليس كذلك.

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