سؤال

أقوم بتحويل التعليمات البرمجية يدويًا من Java إلى C# وأكافح مع (ما أسميه) الأنواع البدائية (انظر ، على سبيل المثال هل تتصرف التآكل التلقائي والملابس بشكل مختلف في Java و C#). من الإجابات أفهم ذلك double (C#) و Double (ج#) معادلة و double (C#) يمكن أيضًا استخدامها في الحاويات ، على سبيل المثال كمفتاح في القاموس. لكن، double (جافا) لا يمكن استخدام Double (جافا).

  1. هو double (ج#) بدائية أم كائن؟
  2. إذا كان بدائيًا ما الذي يجعله يتصرف بشكل مختلف عن double (جافا)؟

double (C#) لا يمكن ضبطه على NULL ما لم يتم صنعه nullable.

  1. هو double? (ج#) يعادل Double (جافا)؟ هل يشار إلى كلاهما كأشياء؟

(هل استخدام مصطلح "كائن من الدرجة الأولى" مفيد في هذه المناقشة؟)

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

المحلول

كل من C# و Java لهما أنواع بدائية (أو "قيمة"): int ، مزدوجة ، تعويم ، إلخ ...

ومع ذلك ، بعد هذا C# و Java يميلان إلى الانقسام.

Java لديها أنواع فئة التفاف ل كل الأنواع البدائية (وهي مجموعة محدودة صغيرة في Java) والتي تسمح لهم بمعاملتها ككائن.double/Double, int/Integer, bool/Boolean, ، إلخ null هي قيمة صالحة لتعيين هذه التعبيرات/المتغيرات المكتوبة. تضيف الإصدارات الحديثة من Java (1.5/5+) إكراه ضمني من البدائية إلى غلافها المقابل.

// Java
Boolean b = true; // implicit conversion boolean -> Boolean (Java 5+)
Boolean b = null; // okay, can assign null to a reference type
boolean n = null; // WRONG - null is not a boolean!

C# لا يوفر مثل هذا الالتفاف المباشر1 - جزئيًا ، لأن C# يدعم مجموعة لا حصر لها من أنواع القيمة عبر الهياكل; ؛ بدلاً من ذلك ، يتعامل C# Nullable<T> نوع الغلاف. بالإضافة إلى ذلك C#، مثل Java ، لديه تحويلات ضمنية من نوع القيمة T ل Nullable<T>, ، مع التقييد على أن t هو "ليس نوعا لاغية" نفسه.

// C#
Nullable<bool> b = true; // implicit conversion bool -> bool?
bool? b = true;          // short type syntax, implicit conversion
bool? b = null;          // okay, can assign null as a Nullable-type
bool b = null;           // WRONG - null is not a bool

لاحظ أن Nullable<T> هو أيضًا نوع قيمة ، وبالتالي يتبع قواعد الهيكل القياسي لمتى/إذا كانت القيمة "على المكدس" أو لا.

ردا على التعليق:

من الصحيح تمامًا ، أن كونه من نوع القيمة يسمح له ببصمة ذاكرة أكثر إحكاما في بعض الحالات لأنه يمكن أن يتجنب النفقات العامة للذاكرة من نوع المرجع: ما هي بصمة الذاكرة من قابلية لا لبسu003CT>. ومع ذلك ، فإنه لا يزال يتطلب ذاكرة أكثر من النوع غير القابل للفرق لأنه يجب أن يتذكر ما إذا كانت القيمة ، حسناً ، لاغية ، أم لا. اعتمادًا على مشكلات المحاذاة وتنفيذ VM ، قد يكون هذا أو لا يكون أقل بكثير من كائن "كامل". أيضًا ، نظرًا لأن القيم في C#/CLR يتم إعادة صياغتها ، فكر في أي عمليات رفع يجب تنفيذها:

// C#
object x = null;
x = (bool?)true;
(x as bool?).Value // true

المقالة جافا نصيحة 130: هل تعرف حجم بياناتك؟ يتحدث عن استهلاك ذاكرة النوع المرجعي (في Java). شيء واحد يجب ملاحظة أن JVM لديه إصدارات متخصصة من المصفوفات داخليًا ، واحدة لكل نوع بدائي وللأشياء (ومع ذلك ، يرجى ملاحظة أن هذه المقالة تحتوي على بعض بيانات مضللة). لاحظ كيف أن الكائنات (مقابل البدائية) تتحمل النفقات العامة للذاكرة ومشكلات محاذاة البايت. C# ومع ذلك ، يمكن أن تمدد حالة الجائزة المحسنة ل Nullable<T> الأنواع مقابل الحالات الخاصة المحدودة التي لدى JVM بسبب Nullable<T> هو نفسه مجرد نوع بنية (أو "بدائية").

ومع ذلك ، فإن الكائن ، يتطلب فقط حجمًا ثابتًا صغيرًا للحفاظ على "مرجع" له في فتحة متغيرة. فتحة متغيرة من النوع Nullable<LargeStruct> من ناحية أخرى ، يجب أن يكون لديه مساحة ل LargeStruct+Nullable (قد تكون الفتحة نفسها على الكومة). يرى C# المفاهيم: القيمة مقابل الأنواع المرجعية. لاحظ كيف يكون مثال "الرفع" أعلاه من النوع object: object هو "نوع الجذر" في C# (الوالد من كل من أنواع المرجع وأنواع القيمة) و ليس نوع القيمة المتخصصة.


1 تدعم لغة C# مجموعة ثابتة من اسماء مستعارة بالنسبة للأنواع البدائية/الشائعة التي تسمح بالوصول إلى أسماء الأنواع "الودية الصغيرة". على سبيل المثال، double هو الاسم المستعار ل System.Double و int هو الاسم المستعار ل System.Int32. ما لم يختلف Double تم استيراد النوع في النطاق ، double و Double سوف تشير إلى نفس النوع في C#. أوصي باستخدام الاسم المستعار ما لم يكن هناك سبب للقيام بخلاف ذلك.

نصائح أخرى

Nullable<double> (الملقب ب double?) في C# ليس نفس أ Double في جافا.

قبل أن يكون لدى Java autoboxing/unboxing ، كان عليك التحويل يدويًا بين البدائية والكائنات من الدرجة الأولى:

Double dblObj = new Double(2.0);
double dblPrim = dblObj.doubleValue();

في Java 1.5 التي تغيرت ، لذلك يمكنك فقط القيام:

Double dblObj = 2.0;
double dblPrim = dblObj;

وسيقوم Java بإدراج رمز لتعكس المثال أعلاه تلقائيًا.

C# مختلف لأن هناك عدد غير محدود من الأنواع "البدائية" (ما يطلق عليه CLR أنواع القيمة). هذه تتصرف في الغالب مثل بدلات جافا ، باستخدام قيمة الدلالات. يمكنك إنشاء أنواع قيمة جديدة باستخدام struct الكلمة الرئيسية. C# لديه autoboxing/unboxing الكل أنواع القيمة ، ويجعل جميع أنواع القيمة مستمدة من Object.

حتى تتمكن من استخدام نوع القيمة (مثل double) حيث يمكنك استخدام أي مرجع كائن (على سبيل المثال كمفتاح في أ Dictionary) وسيتم تعبئتها إذا لزم الأمر ، أو استخدامها مباشرة. (تنفيذ الأداء الوطني لـ C#جيد بما يكفي لتجنب الملاكمة في معظم الظروف.)

في C#، فإن أفضل طريقة لفصل الكائنات هي "أنواع القيمة" التي تشبه البدائية - intس، boolS ، إلخ و "الأنواع المرجعية" - فئات إلخ.

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