سؤال

أنا أقوم بتصميم لغة ، وأتساءل عما إذا كان من المعقول جعل أنواع المرجعية غير قابلة للفرق افتراضيًا ، واستخدام "؟" لقيمة قابلة للارتداء وأنواع المرجع.هل هناك أي مشاكل مع هذا؟ماذا ستفعل حيال هذا:

class Foo {
    Bar? b;
    Bar b2;
    Foo() {
        b.DoSomething(); //valid, but will cause exception
        b2.DoSomething(); //?
    }
}
هل كانت مفيدة؟

المحلول

تتمثل فلسفتي الحالية في تصميم اللغة في أن قابلية الإلغاء يجب أن تكون شيئًا يجبر المبرمج على المطالبة به، ولا يتم تقديمه افتراضيًا في أنواع المراجع (في هذا، أتفق مع توني هور - Google في حديثه الأخير عن QCon).

في هذا المثال المحدد، مع b2 غير القابل للإلغاء، لن ينجح حتى في اجتياز عمليات التحقق الثابتة:لا يمكن للتحليل المحافظ أن يضمن أن b2 ليس NULL، وبالتالي فإن البرنامج ليس له معنى دلالي.

روحي بسيطة بما فيه الكفاية.المراجع هي مؤشر غير مباشر لبعض الموارد، والتي يمكننا اجتيازها للوصول إلى هذا المورد.المراجع الفارغة هي أيضاً مقبض غير مباشر لمورد، أو إشعار بأن المورد غير متوفر، ولا يمكن للمرء التأكد مقدمًا من الدلالات المستخدمة.وهذا يعطي عددًا كبيرًا من الشيكات مقدمًا (هل هو فارغ؟لا؟ياي!) أو NPE الحتمي (أو ما يعادله).معظم موارد البرمجة، في هذه الأيام، ليست مقيدة بشكل كبير بالموارد أو مرتبطة ببعض النماذج الأساسية المحدودة - المراجع الفارغة هي، بشكل مبسط، واحدة من...

  • الكسل:"سأقوم فقط بإحداث خطأ هنا".وهو بصراحة، ليس لدي الكثير من التعاطف معه
  • ارتباك:"لا أعرف ماذا أضع هنا بعد".عادةً ما يكون ذلك أيضًا إرثًا من اللغات القديمة، حيث كان عليك الإعلان عن أسماء الموارد الخاصة بك قبل أن تعرف ما هي مواردك.
  • الأخطاء:"لقد حدث خطأ، هنا فارغة".وبالتالي فإن آليات الإبلاغ عن الأخطاء الأفضل تعتبر ضرورية في اللغة
  • حفرة:"أعلم أنه سيكون لدي شيء ما قريبًا، أعطني عنصرًا نائبًا".وهذا له مزايا أكبر، ويمكننا التفكير في طرق لمكافحته.

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

نصائح أخرى

وجود أنواع مرجع تكون غير قيم الفارغة افتراضيا هو الخيار المنطقي الوحيد. نحن تعاني من اللغات وأوقات التشغيل التي ثمل هذا الأمر. يجب عليك القيام به الشيء الصحيح.

وكانت هذه الميزة في المواصفات # . أنها تخلفت لقيم الفارغة المراجع واستخدامها! للإشارة غير nullables. كان هذا لأنهم يريدون التوافق.

في لغتي الحلم (التي كنت على الارجح يكون المستخدم الوحيد!) فما استقاموا لكم فاستقيموا جعل الخيار نفسه كما كنت، غير قيم الفارغة بشكل افتراضي.

وأود أيضا أن جعله غير قانوني لاستخدام. مشغل في إشارة قيم الفارغة (أو أي شيء آخر من شأنه أن dereference عليه). كيف يمكنك استخدامها؟ كنت قد لتحويلها إلى غير nullables والعشرين. كيف يمكنك أن تفعل هذا؟ عن طريق اختبار لهم لاغية.

في جاوة وC #، ويمكن بيان if تقبل سوى تعبير اختبار bool. فما استقاموا لكم فاستقيموا توسيع نطاقه ليشمل قبول اسم متغير مرجع قيم الفارغة:

if (myObj)
{
    // in this scope, myObj is non-nullable, so can be used
}

وهذا بناء جملة خاص سيكون مفاجئا للمبرمجين C / C ++. كنت تفضل بناء جملة خاص مثل هذا أن يكون واضحا أن نقوم به شيك بتعديل نوع myObj اسم داخل فرع الحقيقة.

وكنت أضيف قليلا مزيد من السكر:

if (SomeMethodReturningANullable() into anotherObj)
{
    // anotherObj is non-nullable, so can be used
}

وهذا يعطي فقط anotherObj اسم لنتيجة التعبير على يسار into، لذلك يمكن استخدامها في نطاق حيث لم يصح.

وكنت تفعل نفس النوع من الشيء للمشغل ?:.

string message = GetMessage() into m ? m : "No message available"; 

لاحظ أن string message غير قابلة للقيم الفارغة، ولكن حتى هما النتائج المحتملة لاختبار أعلى، وبالتالي فإن المهمة هو القيمة.

وبعد ذلك ربما قليلا من السكر للقضية المشتركة يفترض من استبدال قيمة لاغية:

string message = GetMessage() or "No message available";

من الواضح أن or إلا أن تطبق بصورة صحيحة إلى نوع قيم الفارغة على الجانب الأيسر، وغير قيم الفارغة على الجانب الأيمن.

و(فما استقاموا لكم فاستقيموا أيضا المدمج في مفهوم الملكية لحقول سبيل المثال؛ فإن المترجم توليد طريقة IDisposable.Dispose تلقائيا، وسوف بناء الجملة ~Destructor أن تستخدم لزيادة Dispose، تماما كما في C ++ / CLI)

والمواصفات # زيارتها تمديد النحوي آخر يتعلق غير nullables، ويرجع ذلك إلى مشكلة ضمان غير nullables-تم تهيئة بشكل صحيح أثناء عملية البناء:

class SpecSharpExampleClass
{
    private string! _nonNullableExampleField;

    public SpecSharpExampleClass(string s)
        : _nonNullableExampleField(s) 
    {

    }
}

وبعبارة أخرى، لديك لتهيئة الحقول في بنفس الطريقة التي كنت أدعو منشئات أخرى مع base أو this - ما لم يكن بالطبع يمكنك تهيئة لهم مباشرة بجانب إعلان الحقل

بعض الأمثلة على الميزات المماثلة في اللغات الأخرى:

هناك ايضا Nullable<T> (من C#) ولكن هذا ليس مثالًا جيدًا بسبب اختلاف معاملة المرجع مقابل المرجع.أنواع القيمة.

في المثال الخاص بك يمكنك إضافة عامل إرسال رسالة مشروطة، على سبيل المثال.

b?->DoSomething();

لإرسال رسالة إلى b فقط إذا كانت غير فارغة.

اجعل القابلية للإلغاء بمثابة إعداد تكوين وقابل للتنفيذ في مصدر المؤلفين شفرة.بهذه الطريقة، ستسمح للأشخاص الذين يحبون الكائنات الخالية افتراضيًا بالاستمتاع بها في كود المصدر الخاص بهم، بينما تسمح لأولئك الذين يرغبون في أن تكون جميع كائناتهم غير قابلة للقيمة افتراضيًا بالحصول على ذلك بالضبط.بالإضافة إلى ذلك، قم بتوفير كلمات رئيسية أو تسهيلات أخرى لوضع علامة واضحة على أي من إعلاناتك للكائنات والأنواع يمكن أن تكون فارغة وأيها لا يمكن أن تكون فارغة، مع شيء من هذا القبيل nullable و not-nullable, لتجاوز الإعدادات الافتراضية العالمية.

على سبيل المثال

/// "translation unit 1"

#set nullable
{ /// Scope of default override, making all declarations within the scope nullable implicitly
     Bar bar; /// Can be null
     non-null Foo foo; /// Overriden, cannot be null
     nullable FooBar foobar; /// Overriden, can be null, even without the scope definition above 
}

/// Same style for opposite

/// ...

/// Top-bottom, until reset by scoped-setting or simply reset to another value
#set nullable;

/// Nullable types implicitly

#clear nullable;

/// Can also use '#set nullable = false' or '#set not-nullable = true'. Ugly, but human mind is a very original, mhm, thing.

يجادل الكثير من الناس بأن إعطاء الجميع ما يريدون أمر مستحيل، ولكن إذا كنت تصمم لغة جديدة، فجرب أشياء جديدة.قدم توني هور مفهوم null عام 1965 لأنه لم يستطع المقاومة (بكلماته)، ونحن ندفع ثمن ذلك منذ ذلك الحين (بكلماته أيضًا، الرجل نادم على ذلك).النقطة المهمة هي أن الأشخاص الأذكياء وذوي الخبرة يرتكبون أخطاء تكلفنا بقيتنا، فلا تأخذ نصيحة أي شخص في هذه الصفحة كما لو كانت الحقيقة الوحيدة، بما في ذلك نصيحتي.تقييم والتفكير في الأمر.

لقد قرأت الكثير من الأحاديث الصاخبة حول كيف أننا نحن المبرمجين الفقراء عديمي الخبرة الذين لا نفهم حقًا أين نستخدم حقًا null وحيثما لا، يُظهر لنا الأنماط والأنماط المضادة التي تهدف إلى منع إطلاق النار على أقدامنا.وفي الوقت نفسه، يقوم الملايين من المبرمجين الذين لا يتمتعون بالخبرة بإنتاج المزيد من التعليمات البرمجية باللغات التي تسمح بذلك null.أنا ربما عديمي الخبرة، ولكني أعرف أيًا من الأشياء التي لا تستفيد من كونها لاغية.

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

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

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