سؤال

هذا السؤال لديه بالفعل إجابة هنا:

لدي هذا الرمز.

byte dup = 0;
Encoding.ASCII.GetString(new byte[] { (0x80 | dup) });

عندما أحاول التجميع أحصل على:

لا يمكن تحويل النوع "int" ضمنيًا إلى "بايت".يوجد تحويل صريح (هل تفتقد ممثلين؟)

لماذا يحدث هذا؟لا ينبغي | بايتان يعطيون بايت؟يعمل كل من العملين التاليين، مع التأكد من أن كل عنصر هو بايت.

Encoding.ASCII.GetString(new byte[] { (dup) });
Encoding.ASCII.GetString(new byte[] { (0x80) });
هل كانت مفيدة؟

المحلول

إنه بهذه الطريقة من خلال التصميم في C#، وفي الواقع، يعود تاريخه إلى C/C++ - وهذا الأخير يروج أيضًا للمعاملات int, ، أنت عادة لا تلاحظ ذلك int -> char التحويل هناك ضمني، في حين أنه ليس في C#.هذا لا ينطبق فقط على | إما، ولكن لجميع المعاملات الحسابية والمعاملات الثنائية - على سبيل المثال.إضافة اثنين byteسوف أعطيك int أيضًا.سأقتبس الجزء ذي الصلة من المواصفات هنا:

يحدث الترويج الرقمي الثنائي لمعاملات المعاملات السابقة +، - ، *، /، ٪ ، & ، | ، ^، == ،! = ،> ، <،> = ، و <= المشغلات الثنائية.يحول الترويج الرقمي الثنائي ضمناً كلا المعاملين إلى نوع مشترك والذي ، في حالة المشغلين غير العلميين ، يصبح أيضًا نوع النتيجة للعملية.يتكون الترويج الرقمي الثنائي من تطبيق القواعد التالية ، بالترتيب الذي يظهرون هنا:

  • إذا كان إما المعامل من النوع العشري ، يتم تحويل المعامل الآخر إلى نوع عشري ، أو يحدث خطأ في وقت الترجمة إذا كان المعامل الآخر من النوع العائم أو مزدوج.

  • خلاف ذلك ، إذا كان أي من المعاملين من النوع المزدوج ، يتم تحويل المعامل الآخر إلى نوع مزدوج.

  • خلاف ذلك ، إذا كان أي من المعامل من النوع تعويم ، يتم تحويل المعامل الآخر إلى Type Float.

  • خلاف ذلك ، إذا كان أي من المعامل من النوع Ulong ، يتم تحويل المعامل الآخر إلى نوع Ulong ، أو يحدث خطأ في وقت الترجمة إذا كان المعامل الآخر من النوع sbyte أو قصير أو int أو طويل.

  • خلاف ذلك ، إذا كان أي من المعاملين طويلًا ، يتم تحويل المعامل الآخر إلى الكتابة الطويل.

  • خلاف ذلك ، إذا كان أي من المعامل من النوع uint والمعامل الآخر هو من النوع sbyte أو قصير أو int ، يتم تحويل كلا المعاملين إلى نوع طويل.

  • خلاف ذلك ، إذا كان أي من المعاملين من نوع UINT ، يتم تحويل المعامل الآخر إلى نوع UINT.

  • خلاف ذلك ، يتم تحويل كلا المعاملين إلى نوع int.

لا أعرف السبب الدقيق لذلك، ولكن يمكنني التفكير في واحد.بالنسبة للعوامل الحسابية على وجه الخصوص، قد يكون الأمر مفاجئًا بعض الشيء بالنسبة للناس (byte)200 + (byte)100 يساوي فجأة 44, ، حتى لو كان ذلك منطقيًا عندما يدرس المرء بعناية الأنواع المعنية.على الجانب الآخر، int يعتبر بشكل عام نوعًا "جيدًا بما يكفي" للحساب في معظم الأعداد النموذجية، لذلك من خلال ترقية كلا الوسيطتين إلى int, ، تحصل على نوع من السلوك "الفعال فقط" لمعظم الحالات الشائعة.

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

لكن هذا كله تخمين في الغالب.من المحتمل أن يكون إريك ليبرت هو من يسأل عن الدوافع الحقيقية وراء هذا القرار بالنسبة لـ C# على الأقل (على الرغم من أنه سيكون مملًا بعض الشيء إذا كانت الإجابة ببساطة "إنها الطريقة التي يتم بها ذلك في C/C++ وJava، وهي طريقة جيدة بما فيه الكفاية" القاعدة كما هي، لذلك لم نرى أي سبب لتغييرها").

نصائح أخرى

يحتوي الرقم 0x80 الحرفي على النوع "int"، لذا فأنت لا تقوم بتجميع البايتات.

يمكنك تمريره إلى البايت [] يعمل فقط لأن 0x80 (كحرفي) يقع ضمن نطاق البايت.

يحرر:حتى لو تم تحويل 0x80 إلى بايت، فلن يتم تجميع الكود، نظرًا لأن بايتات oring ستظل تعطي قيمة int.لتجميعها، يجب إلقاء نتيجة or: (byte)(0x80|dup)

byte dup = 0;
Encoding.ASCII.GetString(new byte[] { (byte)(0x80 | dup) });

نتيجة البت أو (|) على بايتين هي دائمًا int.

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