لماذا C# الحد من مجموعة من الأنواع التي يمكن أن تكون أعلن const?

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

  •  22-07-2019
  •  | 
  •  

سؤال

خطأ برنامج التحويل البرمجي CS0283 يشير إلى أنه الأساسية فقط جراب أنواع (وكذلك السلاسل ، enums null المراجع) يمكن أن أعلن عن const.هل من أحد لديه نظرية عن مبررات هذا التقادم ؟ على سبيل المثال, سيكون من الجميل أن تكون قادرة على أن تعلن const القيم من أنواع أخرى ، مثل IntPtr.

أعتقد أن مفهوم const هو في الواقع النحوية السكر في C#, و أنه فقط يستبدل أي يستخدم الاسم مع القيمة الحرفية.على سبيل المثال, نظرا التالية إعلان أي إشارة إلى فو بعبارة "فو" في وقت الترجمة.

const string Foo = "foo";

هذا من شأنه أن يستبعد أي قابلة للتغيير أنواع, لذلك ربما اختاروا هذا القيد بدلا من الاضطرار إلى تحديد في وقت الترجمة ما إذا كان نوع معين هي قابلة للتغيير?

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

المحلول

من C# مواصفات الفصل 10.4 - الثوابت:
(10.4 في C# 3.0 مواصفات 10.3 في الإصدار 2.0)

ثابت هو عضو الفئة التي تمثل قيمة ثابتة:القيمة التي يمكن أن تحسب في وقت الترجمة.

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

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

فقط القانوني المستمر نوع القيمة سبيل المثال لا يمكن أن يفكر في أن يكون أحد تهيئته مع أصفار فقط معلنا أنه لا يكاد مفيدة.

أما عن كيفية مترجم يعامل/يستخدم الثوابت ، فإنه سيتم استخدام احتساب القيمة في مكان اسم ثابت في المدونة.

وبالتالي يجب النتيجة التالية:

  • أي إشارة إلى الأصل اسم ثابت, فئة أعلن في ، أو مساحة الاسم ، يتم ترجمة التعليمات البرمجية في هذا الموقع
  • إذا كنت فك رمز, سيكون لديك الأرقام السحرية في ذلك, ببساطة لأن الأصل "إشارة" إلى المستمر ، كما ذكر أعلاه ، ليس فقط قيمة ثابتة
  • المترجم يمكن استخدام هذا لتحسين أو حتى إزالة لا لزوم لها رمز.فعلى سبيل المثال ، if (SomeClass.Version == 1), عندما SomeClass.الإصدار يحتوي على قيمة 1 ، في الواقع إزالة إذا-بيان والحفاظ على كتلة من التعليمات البرمجية يتم تنفيذه.إذا كانت قيمة ثابت هو 1 ، وبعد ذلك كله إذا-بيان كتلة سيتم إزالتها.
  • لأن قيمة ثابتة يتم ترجمة الكود و لا إشارة إلى ثابت ، باستخدام الثوابت من جمعيات أخرى لن التلقائى تحديث التعليمات البرمجية المترجمة في أي وسيلة إذا كانت قيمة ثابت أن التغيير (الذي لا ينبغي!)

وبعبارة أخرى, مع السيناريو التالي:

  1. الجمعية, يحتوي ثابت اسمه "نسخة" ، وجود قيمة 1
  2. الجمعية ب, يحتوي التعبير الذي يحلل رقم الإصدار من الجمعية من أن ثابت و يقارن إلى 1 ، للتأكد من أنها يمكن أن تعمل مع الجمعية
  3. شخص يعدل الجمعية ، وزيادة قيمة ثابتة إلى 2 ، و هدمه (ولكن ليس ب)

في هذه الحالة, الجمعية ب في تجميع النموذج وسوف لا يزال مقارنة قيمة من 1 إلى 1 ، لأنه عندما ب جمعت المستمر قيمة 1.

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

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

لذلك هذا هو موافق:

  • public const Int32 NumberOfDaysInAWeekInGregorianCalendar = 7;
  • public const Int32 NumberOfHoursInADayOnEarth = 24;

في حين أن هذا ليس:

  • public const Int32 AgeOfProgrammer = 25;
  • public const سلسلة NameOfLastProgrammerThatModifiedassembly = "جو مبرمج";

تحرير 27 مايو 2016

حسنا, فقط حصلت على upvote ، لذلك أنا أعيد قراءة جوابي هنا و هذا هو في الواقع قليلا خاطئ.

الآن ، نية من لغة C# مواصفات كل ما كتبته أعلاه.أنت ليس من المفترض أن تستخدم شيئا لا يمكن أن تكون ممثلة مع الحرفي كما const.

ولكن يمكن لك ؟ نعم....

دعونا نلقي نظرة على decimal نوع.

public class Test
{
    public const decimal Value = 10.123M;
}

دعونا ننظر إلى ما في هذا الفصل يبدو حقا عندما نظرت مع ildasm:

.field public static initonly valuetype [mscorlib]System.Decimal X
.custom instance void [mscorlib]System.Runtime.CompilerServices.DecimalConstantAttribute::.ctor(int8, uint8, uint32, uint32, uint32) = ( 01 00 01 00 00 00 00 00 00 00 00 00 64 00 00 00 00 00 ) 

دعني أوضح لك:

.field public static initonly

يتوافق مع:

public static readonly

هذا صحيح ، const decimal هو في الواقع readonly decimal.

الصفقة الحقيقية هنا هي أن المترجم استخدام هذا DecimalConstantAttribute سحرها.

الآن, هذا هو فقط مثل السحر أعرف مع برنامج التحويل البرمجي C# ولكن أعتقد أنه كان يستحق الذكر.

نصائح أخرى

<اقتباس فقرة>   

هل لديها نظرية على الأساس المنطقي لهذا الحد؟

إذا هو سمح لها أن تكون مجرد نظرية، نظريتي هي أن القيم CONST من أنواع بدائية يمكن التعبير عنها في المعلمات شفرة تشغيل الحرفية في MSIL ... ولكن قيم أنواع أخرى، غير بدائية لا يمكن، لأن MSIL لا توجد الآن ' ر لها بناء الجملة للتعبير عن قيمة نوع المعرفة من قبل المستخدم وحرفي.

<اقتباس فقرة>   

وأعتقد أن مفهوم CONST هو في الواقع نحوي السكر في C #، وأنه مجرد استبدال أي استخدامات الاسم مع قيمة حرفية

وماذا تفعل مترجم مع كائنات CONST في لغات أخرى؟

ويمكنك استخدام للقراءة فقط لأنواع قابلة للتغيير أن لي أن أكون وتقييمها في وقت التشغيل. انظر هذه المقالة للاختلافات.

تقتصر

وconsts إلى الأرقام والسلاسل في C # لأن المترجم محل المتغير مع قيمة حرفية في MSIL. وبعبارة أخرى عندما تكتب:

const string myName = "Bruce Wayne";
if (someVar == myName)
{
   ...
}

ويتم التعامل مع الواقع كما

if (someVar == "Bruce Wayne")
{
   ...
}

وونعم، C # مترجم ذكي بما فيه الكفاية لعلاج المشغل المساواة (==) على سلاسل ك

string1.Equals(string2)

ويبدو لي أن أنواع القيمة فقط يمكن التعبير عن ثابت (باستثناء السلاسل، والتي تقف في مكان ما بين القيمة ونوع الكائن).

وعلى ما يرام بالنسبة لي: الكائنات (المراجع) يجب تخصيص على كومة لكن لا يتم تخصيص الثوابت على الإطلاق (لأنها يتم استبدالها في وقت الترجمة)

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

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