سؤال

بسبب خطأ تم إصلاحه في C# 4، تتم طباعة البرنامج التالي true.(جربه في LINQPad)

void Main() { new Derived(); }

class Base {
    public Base(Func<string> valueMaker) { Console.WriteLine(valueMaker()); }
}
class Derived : Base {
    string CheckNull() { return "Am I null? " + (this == null); }
    public Derived() : base(() => CheckNull()) { }
}

في VS2008 في وضع الإصدار، فإنه يطرح InvalidProgramException.(في وضع التصحيح، يعمل بشكل جيد)

في VS2010 Beta 2، لا يتم تجميعه (لم أجرب Beta 1)؛تعلمت هذا بصعوبة

هل هناك أي طريقة أخرى لجعل this == null في C # النقي؟

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

المحلول

تم نشر هذه الملاحظة على StackOverflow في سؤال آخر في وقت سابق من اليوم.

ماركإجابة عظيمة على هذا السؤال يشير إلى أنه وفقًا للمواصفات (القسم 7.5.7)، من المفترض ألا تتمكن من الوصول this في هذا السياق والقدرة على القيام بذلك في برنامج التحويل البرمجي C# 3.0 يعد خطأً.يتصرف مترجم C# 4.0 بشكل صحيح وفقًا للمواصفات (حتى في الإصدار التجريبي 1، يعد هذا خطأ في وقت الترجمة):

§ 7.5.7 هذا الوصول

أ هذا الوصول يتكون من الكلمة المحجوزة this.

هذا الوصول:

this

أ هذا الوصول لا يجوز إلا في حاجز لمنشئ المثيل، أو أسلوب المثيل، أو موصل المثيل.

نصائح أخرى

ووبتفريغ الخام (العاكس مع عدم وجود تحسينات) من ثنائي وضع التصحيح هو:

private class Derived : Program.Base
{
    // Methods
    public Derived()
    {
        base..ctor(new Func<string>(Program.Derived.<.ctor>b__0));
        return;
    }

    [CompilerGenerated]
    private static string <.ctor>b__0()
    {
        string CS$1$0000;
        CS$1$0000 = CS$1$0000.CheckNull();
    Label_0009:
        return CS$1$0000;
    }

    private string CheckNull()
    {
        string CS$1$0000;
        CS$1$0000 = "Am I null? " + ((bool) (this == null));
    Label_0017:
        return CS$1$0000;
    }
}

وطريقة CompilerGenerated لا معنى له. إذا نظرتم إلى IL (أدناه)، فإنه استدعاء الأسلوب على باطل <م> سلسلة (!).

   .locals init (
        [0] string CS$1$0000)
    L_0000: ldloc.0 
    L_0001: call instance string CompilerBug.Program/Derived::CheckNull()
    L_0006: stloc.0 
    L_0007: br.s L_0009
    L_0009: ldloc.0 
    L_000a: ret 

في وضع الإصدار، هو الأمثل لمتغير محلي بعيدا، لذلك يحاول دفع متغير غير existant إلى المكدس.

    L_0000: ldloc.0 
    L_0001: call instance string CompilerBug.Program/Derived::CheckNull()
    L_0006: ret 

و(أعطال العاكس عند تحويله إلى C #)


تعديل : في؟ لا أحد (؟ اريك ليبرت) أعرف لماذا المترجم تنبعث ldloc

ولقد كان ذلك! (وحصلت على دليل ايضا)

وهذه ليست "علة". هذا هو أنت إساءة استخدام النظام نوع. كنت أبدا المفترض لتمرير إشارة إلى الحالة الراهنة (this) إلى أي شخص داخل المنشئ.

وأنا يمكن أن يخلق "علة" مماثل من قبل استدعاء أسلوب الظاهري داخل منشئ الفئة الأساسية أيضا.

وفقط لأنك <م> يمكن تفعل شيئا سيئا لا يعني لها لعلة عندما تحصل قليلا منه.

ويمكن أن أكون مخطئا، ولكن أنا متأكد إذا الكائن هو null هناك أبدا سيكون سيناريو حيث ينطبق this.

وعلى سبيل المثال، كيف ندعو CheckNull؟

Derived derived = null;
Console.WriteLine(derived.CheckNull()); // this should throw a NullReferenceException

ولست متأكدا إذا كان هذا هو ما كنت تبحث عن

    public static T CheckForNull<T>(object primary, T Default)
    {
        try
        {
            if (primary != null && !(primary is DBNull))
                return (T)Convert.ChangeType(primary, typeof(T));
            else if (Default.GetType() == typeof(T))
                return Default;
        }
        catch (Exception e)
        {
            throw new Exception("C:CFN.1 - " + e.Message + "Unexpected object type of " + primary.GetType().ToString() + " instead of " + typeof(T).ToString());
        }
        return default(T);
    }

وعلى سبيل المثال: معرف المستخدم = CheckForNull (Request.QueryString [ "معرف المستخدم"]، 147)؛

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