مقارنة بين لغتي سي شارب وجافا

تقارن هذه المقالة بين لغتي برمجة : C# و Java . وبينما يركز هذا المقال بشكل أساسي على اللغتين وخصائصهما، فإن هذه المقارنة ستأخذ بالضرورة في الاعتبار بعض خصائص المنصات والمكتبات .

تُعتبر لغتا C# و Java لغتين متشابهتين، تتميزان بالكتابة الثابتة والقوية والواضحة . كلتاهما لغتان كائنية التوجه ، ومصممتان بتقنية الترجمة شبه التفسيرية أو الترجمة الفورية أثناء التشغيل ، وكلتاهما لغتان تستخدمان الأقواس المعقوفة ، مثل لغتي C و C++ .

الأنواع

أنواع البياناتجافاسي شارب
أعداد عشرية ذات حجم عشوائينوع مرجعي؛ لا توجد عوامل تشغيل [ 1 ]مكتبة الطرف الثالث [ 2 ]
أعداد صحيحة ذات حجم عشوائينوع مرجعي؛ بدون عوامل تشغيلنعم [ 3 ]
المصفوفاتنعم [ 4 ]نعم
نوع منطقينعمنعم
شخصيةنعم [ 5 ]نعم
الأعداد المركبةمكتبة الطرف الثالث [ 6 ]نعم
التاريخ/الوقتنعم؛ نوع المرجع [ 7 ]نعم؛ نوع القيمة
أنواع مُعَدَّةنعم؛ نوع المرجعنعم؛ كمية قياسية
رقم عشري عالي الدقةلا؛ ولكن انظر "الأعداد العشرية ذات الحجم العشوائي" أعلاهنوع عشري 128 بت (28 رقمًا) [ 8 ]
IEEE 754 binary32 عدد الفاصلة العائمةنعمنعم
رقم الفاصلة العائمة ثنائي 64 بت وفقًا لمعيار IEEE 754نعمنعم
أنواع مرفوعة (قابلة للتصفير)لا؛ ولكن أنواع التغليفنعم
نصائحلا؛ تتجنب لغة جافا استخدام المؤشرات لضمان سلامة الذاكرة وجمع البيانات المهملة تلقائيًانعم [ 9 ]
أنواع المراجعنعمنعم
الأعداد الصحيحة الموقعةنعم؛ 8 ، 16 ، 32 ، 64 بتنعم؛ 8، 16، 32، 64 بت
الأوتارنوع مرجعي غير قابل للتغيير، يونيكودنوع مرجعي غير قابل للتغيير، يونيكود
التعليقات التوضيحية للأنواعنعمنعم
نظام النوع ذو الجذر الواحد (الموحد)نعم [ 10 ]نعم [ 11 ]
المجموعاتلا؛ توفر السجلات والمكتبات وظائف مماثلة.نعم [ 12 ] [ 13 ]
الأعداد الصحيحة غير الموقعةلا؛ العمليات مدعومة عبر طرق المكتبةنعم؛ 8، 16، 32، 64 بت
أنواع القيمجزئي؛ أنواع بدائية فقطنعم

نظام النوع الموحد

كلتا اللغتين تعتمدان على الكتابة الثابتة مع توجيه كائني قائم على الأصناف. في جافا، تتميز الأنواع الأولية بكونها غير موجهة كائنيًا، ولم يكن من الممكن تعريفها باستخدام اللغة نفسها. كما أنها لا تشترك في سلف مشترك مع الأنواع المرجعية. جميع الأنواع المرجعية في جافا مشتقة من نوع جذري مشترك. أما لغة C#، فلديها نظام أنواع موحد ، حيث تشتق جميع الأنواع (باستثناء المؤشرات غير الآمنة [ 14 ] ) في النهاية من نوع جذري مشترك. ونتيجة لذلك، تُنفذ جميع الأنواع أساليب هذا النوع الجذري، وتُطبق أساليب الإضافة المُعرّفة لنوع الكائن على جميع الأنواع، حتى القيم الحرفية الأولية من نوع int والمفوضين . هذا يسمح للغة C#، على عكس جافا، بدعم الكائنات ذات التغليف التي ليست أنواعًا مرجعية.

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

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

تُطبّق أنواع C# البسيطة العديد من الواجهات ، وبالتالي تُتيح العديد من الدوال مباشرةً على مثيلات هذه الأنواع، حتى على القيم الحرفية. كما أن أسماء أنواع C# هي مجرد أسماء بديلة لأنواع وقت تشغيل اللغة العامة (CLR). نوع C# System.Int64هو نفسه نوع long تمامًا ؛ والفرق الوحيد هو أن الأول هو الاسم المتعارف عليه في .NET ، بينما الثاني هو اسم بديل له في C#.

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

أنواع البيانات

الأنواع الرقمية

الأعداد الصحيحة الموقعة

تدعم كل من لغتي Java وC# الأعداد الصحيحة الموقعة بعرض بتات 8 و16 و32 و64 بت. وتستخدمان نفس الأسماء/الأسماء البديلة للأنواع، باستثناء العدد الصحيح ذي 8 بت الذي يُسمى بايت في Java وبايت مُوقّع ( sbyte ) في C#.

الأعداد الصحيحة غير الموقعة

تدعم لغة C# أنواع الأعداد غير الموقعة بالإضافة إلى أنواع الأعداد الصحيحة الموقعة . تشمل أنواع الأعداد غير الموقعة byte و ushort و uint و ulong، بأطوال بت 8 و 16 و 32 و 64 على التوالي. كما تدعم اللغة العمليات الحسابية على هذه الأنواع. على سبيل المثال، ينتج عن جمع عددين صحيحين غير موقعين ( uint s) عدد صحيح غير موقع (uint ) ، وليس عددًا صحيحًا طويلًا أو موقعًا.

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

تم استبعاد الأعداد الصحيحة غير الموقعة من لغة جافا عمداً لأن جيمس جوسلينج كان يعتقد أن المبرمجين لن يفهموا كيفية عمل العمليات الحسابية غير الموقعة.

في تصميم لغات البرمجة، تتمثل إحدى المشكلات الشائعة في أن اللغة تصبح معقدة لدرجة يصعب معها فهمها. ومن التجارب البسيطة التي أجريتها سؤال الناس عن قواعد الحساب غير الموقّع في لغة C. اتضح أن لا أحد يفهم آلية عمل هذا النوع من الحساب. هناك بعض الأمور البديهية التي يفهمها الناس، لكن الكثيرين لا يفهمونها. [ 16 ] [ 17 ]

أضافت إصدارات جافا 8 و9 بعض العمليات المضمنة المحدودة على الأعداد الصحيحة غير الموقعة، ولكنها متاحة فقط كطرق ثابتة في فئات التغليف الأولية؛ وتعمل على أنواع الأعداد الصحيحة الأولية الموقعة، وتعاملها كما لو كانت غير موقعة. [ 18 ]

أرقام عشرية عالية الدقة

تحتوي لغة C# على نوع وصيغة حرفية للحسابات العشرية عالية الدقة (28 رقمًا عشريًا)، وهي مناسبة للحسابات المالية والنقدية. [ 19 ] [ 20 ] [ 21 ] على عكس نوعي البيانات float و double ، يمكن تمثيل الأعداد العشرية الكسرية، مثل 0.1، بدقة تامة في التمثيل العشري. في تمثيلات float وdouble، غالبًا ما يكون لهذه الأعداد امتدادات ثنائية غير منتهية، مما يجعلها أكثر عرضة لأخطاء التقريب. [ 20 ]

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

أنواع الأرقام المتقدمة

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

لغة جافا هي الوحيدة التي تمتلك نوع بيانات لإجراء حسابات الفاصلة العشرية بدقة عشوائية. لغة سي شارب هي الوحيدة التي تمتلك نوع بيانات للتعامل مع الأعداد المركبة .

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

تتيح لغة C# دمج الأنواع المُعرَّفة في المكتبة مع الأنواع والمعاملات الموجودة باستخدام تحويلات ضمنية/صريحة مخصصة وتحميل المعاملات الزائد. انظر المثال في قسم دمج الأنواع المُعرَّفة في المكتبة

الشخصيات

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

أنواع البيانات المركبة المدمجة

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

تُعرّف مكتبات اللغتين فئاتٍ للتعامل مع التواريخ والأوقات والمناطق الزمنية والتقاويم في ثقافاتٍ مختلفة. توفر جافا نوع مرجعي قابل للتغيير بدقة أجزاء من الألف من الثانية، وحزمة (منذ جافا 8) تتضمن فئات مثل LocalDate و LocalTime و LocalDateTime لقيم التاريخ فقط، والوقت فقط، والتاريخ والوقت معًا)، وهي مجموعة من الأنواع المرجعية غير القابلة للتغيير بدقة أجزاء من النانو ثانية . [ 22 ] في المقابل، تُعدّ C# نوع قيمة هيكلية غير قابلة للتغيير لمعلومات التاريخ والوقت بدقة 100 نانو ثانية؛ كما أضافت واجهة برمجة تطبيقات .NET 6 أيضًا بنيتين مماثلتين لعمليات التاريخ فقط أو الوقت فقط. [ 23 ] تُعرّف C# أيضًا نوعًا للتعامل مع الفترات الزمنية؛ وتوفر جافا 8 الفئة للغرض نفسه. تدعم كلتا اللغتين العمليات الحسابية على التاريخ والوقت وفقًا للثقافات والمناطق الزمنية المختلفة.java.util.Datejava.timeSystem.DateTimeSystem.DateOnlySystem.TimeOnlySystem.TimeSpanjava.time.Duration

نوع القيمة المُعرَّف من قِبل المستخدم (بنية)

تتيح لغة C# للمبرمج إنشاء أنواع قيم مُعرَّفة من قِبل المستخدم ، باستخدام الكلمة المفتاحية struct . على عكس الأصناف، وكما هو الحال مع الأنواع الأولية القياسية، تُمرَّر هذه الأنواع وتُسند إليها القيم مباشرةً بدلاً من الإسناد إليها. كما يمكن أن تكون جزءًا من كائن (إما كحقل أو كعنصر مُغلَّف )، أو تُخزَّن في مصفوفة دون الحاجة إلى توجيه الذاكرة غير المباشر الموجود عادةً لأنواع الأصناف.

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

بصرف النظر عن الأنواع الأولية المضمنة، لا تتضمن لغة جافا مفهوم أنواع القيم.

التعدادات

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

تُطبّق لغة C# التعدادات بطريقة مشابهة للغة C، أي كأغلفة حول علامات البت المُطبّقة في أنواع البيانات الصحيحة الأولية (int، byte، short، إلخ). يُحسّن هذا الأداء ويُسهّل التفاعل مع شيفرة C/C++ المُصرّفة، ولكنه يُوفّر ميزات أقل وقد يُؤدي إلى أخطاء إذا تم تحويل أنواع القيم منخفضة المستوى مباشرةً إلى نوع تعداد، كما هو مسموح به في لغة C#. لذلك، يُنظر إليه على أنه تحسين شكلي . [ 24 ] في المقابل، تُطبّق لغة Java التعدادات كمجموعة كاملة الميزات من النسخ، مما يتطلب ذاكرة أكبر ولا يُحسّن التفاعل مع شيفرة C/C++، ولكنه يُوفّر ميزات إضافية في الانعكاس والسلوك الجوهري. يُوضّح الجدول أدناه كيفية تطبيق التعدادات في كل لغة.

جافاسي شارب
تعريففي لغة جافا، يُعدّ نوع التعداد فئةً ، وقيمه كائنات (نسخ) من تلك الفئة. القيم الصالحة الوحيدة هي تلك المدرجة في التعداد. يمكن لنوع التعداد تعريف حقول ، مما يسمح لكل قيمة مُعدّدة بالرجوع إلى بيانات إضافية مرتبطة بها بشكل فريد. كما يمكن لنوع التعداد تعريف أو إعادة تعريف توابع ، أو تطبيق واجهات . [ 25 ]تُشتق التعدادات في لغة C# ضمنيًا من نوع Enum ، وهو بدوره نوع مشتق من نوع القيمة. تُحدد مجموعة قيم تعداد C# بواسطة النوع الأساسي ، والذي يمكن أن يكون عددًا صحيحًا مُوقّعًا أو غير مُوقّع، بأطوال 8 أو 16 أو 32 أو 64 بت. يُحدد تعريف التعداد أسماءً لقيم الأعداد الصحيحة المُختارة. [ 25 ] [ 26 ] افتراضيًا، يُسند الاسم الأول القيمة 0 (صفر)، وتُسند الأسماء اللاحقة بزيادات قدرها 1. أي قيمة من النوع الأساسي تُعد قيمة صالحة لنوع التعداد، مع العلم أنه قد يلزم إجراء تحويل صريح لإسنادها.
الجمعتوفر مجموعات التعداد والخرائط في جافا وظائف لدمج قيم تعداد متعددة في قيمة واحدة. تسمح هذه المجموعات الخاصة بتحسين أداء المُصرّف لتقليل الحمل الزائد الناتج عن استخدام المجموعات كآلية للدمج.تدعم لغة C# التعدادات ذات الخرائط البتية، حيث قد تكون القيمة الفعلية مزيجًا من قيم مُعدّدة مُدمجة معًا باستخدام عملية OR الثنائية. وستحاول طرق التنسيق والتحليل المُعرّفة ضمنيًا بواسطة النوع استخدام هذه القيم.

في كلٍ من لغتي C# و Java، يُمكن للمبرمجين استخدام التعدادات في عبارة switch دون تحويلها إلى سلسلة نصية أو نوع عدد صحيح أولي. مع ذلك، تمنع لغة C# الانتقال الضمني إلا إذا كانت عبارة case خالية من أي تعليمات برمجية، إذ يُعدّ ذلك سببًا شائعًا للأخطاء التي يصعب اكتشافها. [ 27 ] يجب التصريح عن الانتقال صراحةً باستخدام عبارة goto . [ 28 ]

المندوبون، مراجع المنهجية

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

لا ينبغي الخلط بين المندوبين والإغلاقات والدوال المضمنة. ترتبط هذه المفاهيم ببعضها لأن الإشارة إلى إغلاق/دالة مضمنة يجب أن تُضمّن في مرجع المندوب لتكون مفيدة. لكن المندوب لا يشير دائمًا إلى دالة مضمنة؛ بل يمكنه أيضًا الإشارة إلى دوال ثابتة أو دوال مثيل موجودة. تُشكّل المندوبين أساس أحداث C# ، ولكن لا ينبغي الخلط بينها وبين أحداث C# أيضًا.

تم استبعاد المندوبين عمدًا من لغة جافا لأنهم اعتبروا غير ضروريين ومضرين باللغة، فضلًا عن مشاكل الأداء المحتملة. [ 29 ] وبدلًا من ذلك، تُستخدم آليات بديلة. يُعد نمط التغليف ، الذي يُشبه المندوبين في لغة سي شارب من حيث أنه يسمح للعميل بالوصول إلى طريقة واحدة أو أكثر مُعرّفة من قِبله عبر واجهة معروفة ، إحدى هذه الآليات. وهناك آلية أخرى تتمثل في استخدام كائنات المُهايئ باستخدام الفئات الداخلية، والتي جادل مصممو جافا بأنها حل أفضل من مراجع الطرق المُقيدة. [ 29 ]

انظر أيضًا إلى أمثلة المندوبين في لغة C# والبنى المكافئة في لغة Java .

أنواع مرفوعة (قابلة للتصفير)

تتيح لغة C# رفع أنواع البيانات الأولية/البسيطة/القيمية للسماح باستخدام القيمة الفارغة (null ) بالإضافة إلى القيم الأصلية للنوع. يتم رفع النوع بإضافة لاحقة إلى اسمه؛ وهذا يُعادل استخدام النوع العام ، حيث T هو النوع المراد رفعه. تُعرَّف التحويلات ضمنيًا للتحويل بين قيم النوع الأساسي والنوع المرفوع. يمكن مقارنة النوع المرفوع بالقيمة الفارغة (null) أو اختباره للتأكد من وجود قيمة له (HasValue) . كما تُعرَّف المعاملات المرفوعة ضمنيًا وتلقائيًا بناءً على النوع الأساسي غير المرفوع، حيث - باستثناء بعض المعاملات المنطقية - تنتقل القيمة الفارغة (null) إلى النتيجة.?Nullable<T>

لا تدعم لغة جافا رفع النوع كمفهوم، ولكن جميع الأنواع الأولية المضمنة لها أنواع تغليف مقابلة، والتي تدعم القيمة الفارغة بحكم كونها أنواع مرجعية (فئات).

وفقًا لمواصفات جافا، فإن أي محاولة لفك مرجعية قيمة فارغة (null) ستؤدي إلى ظهور استثناء أثناء التشغيل، وتحديدًا استثناء NullPointerException . (وإلا لما كان من المنطقي فك مرجعية القيمة الفارغة، لأنها، بحكم تعريفها، لا تشير إلى أي كائن في الذاكرة). وينطبق هذا أيضًا عند محاولة فك تغليف متغير من نوع مُغلِّف، والذي يُقيَّم إلى قيمة فارغة (null ): سيُطلق البرنامج استثناءً، لأنه لا يوجد كائن لفك تغليفه، وبالتالي لا توجد قيمة مُغلَّفة للمشاركة في الحساب اللاحق.

يوضح المثال التالي اختلاف السلوك. في لغة C#، يقوم عامل التشغيل lifted* بتمرير القيمة الفارغة للمعامل؛ أما في لغة Java، فإن فك تغليف المرجع الفارغ يؤدي إلى ظهور استثناء.

لم تُعرَّف جميع عوامل التشغيل المُرفَّعة في لغة C# بحيث تُمرِّر القيمة الفارغة (null) بشكلٍ غير مشروط إذا كانت إحدى المعاملات فارغة . على وجه التحديد، تم رفع عوامل التشغيل المنطقية (Boolean) لدعم المنطق الثلاثي، مما يحافظ على التوافق مع لغة SQL .

لا تدعم عوامل التشغيل المنطقية في Java المنطق الثلاثي، كما أنها غير مطبقة في مكتبة الفئة الأساسية.

نوع مرتبط متأخرًا (ديناميكي)

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

توجد عدة حالات استخدام للنوع الديناميكي في لغة C#:

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

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

  • بالنسبة للاستدعاء الديناميكي المتأخر بالاسم للأنواع الموجودة مسبقًا، يجب استخدام الانعكاس.
  • لضمان التوافق مع اللغات الديناميكية، يجب استخدام واجهة برمجة تطبيقات (API) خاصة بتلك اللغة. تحتوي منصة آلة جافا الافتراضية على العديد من اللغات الديناميكية، ولكن لا يوجد معيار موحد لكيفية تمرير الكائنات بين اللغات. عادةً ما يتضمن ذلك استخدام نوع من الانعكاس أو واجهة برمجة تطبيقات شبيهة به. كمثال على كيفية استخدام كائنات JavaFX من جافا. [ 30 ]
  • لإنشاء الكائنات والتفاعل معها بالكامل في وقت التشغيل، على سبيل المثال، التفاعل مع تجريد نموذج كائن المستند، يجب استخدام واجهة برمجة تطبيقات تجريد محددة.

انظر أيضًا المثال #التوافق مع اللغات الديناميكية .

نصائح

تمنع لغة جافا استخدام المؤشرات وعملياتها الحسابية ضمن بيئة تشغيلها. وقد برر مصممو لغة جافا ذلك بأن المؤشرات تُعدّ من أبرز العوامل التي تُتيح للمبرمجين إدخال أخطاء في برامجهم، لذا اختاروا عدم دعمها. [ 16 ] لا تسمح جافا بتمرير واستقبال الكائنات/الهياكل مباشرةً من وإلى نظام التشغيل الأساسي، وبالتالي لا تحتاج إلى نمذجة الكائنات/الهياكل وفقًا لتخطيط ذاكرة مُحدد، وهو تخطيط غالبًا ما يتضمن استخدام المؤشرات. بدلًا من ذلك، تعتمد جافا في تواصلها مع نظام التشغيل الأساسي على واجهة جافا الأصلية (JNI)، حيث تتم إدارة التواصل مع نظام التشغيل الأساسي والتكيف معه من خلال طبقة وسيطة خارجية .

على الرغم من أن لغة C# تسمح باستخدام المؤشرات وعملياتها الحسابية، إلا أن مصممي اللغة كانوا قلقين من إمكانية استغلال المؤشرات للتحايل على قواعد الوصول الصارمة للكائنات. لذا، تمنع C# استخدام المؤشرات افتراضيًا. [ 31 ] مع ذلك، ونظرًا لأهمية المؤشرات عند استدعاء العديد من الدوال الأصلية، يُسمح باستخدامها في وضع غير آمن صريح . يجب وضع علامة " unsafe" على كتل التعليمات البرمجية أو الدوال التي تستخدم المؤشرات لكي تتمكن من استخدامها، ويتطلب المُصرّف استخدام مفتاح التبديل للسماح بتجميع هذا النوع من التعليمات البرمجية. تُعلّم التجميعات التي تُجمّع باستخدام مفتاح التبديل على هذا النحو، ولا يُسمح بتنفيذها إلا إذا كانت موثوقة صراحةً. يتيح هذا استخدام المؤشرات وعملياتها الحسابية لتمرير واستقبال الكائنات مباشرةً من وإلى نظام التشغيل أو واجهات برمجة التطبيقات الأصلية الأخرى باستخدام تخطيط الذاكرة الأصلي لتلك الكائنات، مع عزل هذه التعليمات البرمجية التي قد تكون غير آمنة في تجميعات موثوقة تحديدًا./unsafe/unsafe

أنواع المراجع

في كلتا اللغتين ، تُعدّ المراجع مفهوماً أساسياً. جميع مثيلات الفئات تتم عن طريق المراجع .

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

إلى جانب المراجع الضعيفة، تحتوي لغة جافا على المراجع المرنة . وهي تشبه المراجع الضعيفة إلى حد كبير، ولكن آلة جافا الافتراضية (JVM) لن تُحرر الكائنات ذات المراجع المرنة إلا عند الحاجة إلى الذاكرة.

أنواع المراجعجافاسي شارب
جمع القمامةنعمنعم
مراجع ضعيفةنعمنعم
قائمة المراجع (التفاعل مع عملية جمع البيانات المهملة)نعمنعم
إشارات غير مباشرةنعملا
إشارات وهميةنعملا
دعم البروكسينعم؛ إنشاء وكيلنعم؛ سياقات الكائنات

المصفوفات والمجموعات

تُعدّ المصفوفات والمجموعات من المفاهيم المميزة لكلا اللغتين.

المصفوفات والمجموعاتجافاسي شارب
أنواع البيانات المجردةنعمنعم
مصفوفات أحادية البعد ذات فهرس يبدأ من الصفرنعمنعم
المصفوفات متعددة الأبعاد، المستطيلة (مصفوفة واحدة)لا؛ تستخدم لغة جافا مصفوفات من المصفوفات لتحقيق المرونة وإدارة الذاكرة بشكل أكثر أمانًا.نعم
المصفوفات متعددة الأبعاد، المصفوفات غير المنتظمة (مصفوفات من المصفوفات)نعمنعم
المصفوفات غير الصفريةلا؛ تبدأ مصفوفات جافا دائمًا من الصفر لتبسيط العملية، ولضمان السلامة، ولتحسين كفاءة آلة جافا الافتراضية.بعض
المصفوفات والمجموعات الموحدةلا؛ تحتفظ لغة جافا بالمصفوفات والمجموعات بشكل منفصل لتبسيط الأمور وضمان سلامة الأنواع.نعم
الخرائط/القواميسنعمنعم
قواميس مصنفةنعمنعم [ 32 ]
مجموعاتنعمنعم
المجموعات المصنفةنعمنعم [ 33 ]
القوائم/المتجهاتنعمنعم
الطوابير/المكدساتنعمنعم
قائمة الانتظار ذات الأولويةنعمنعم [ 34 ]
حقائب/مجموعات متعددةمكتبة طرف ثالثنعم
مجموعات مُحسَّنة للتزامننعمنعم [ 35 ]

إن الصيغة المستخدمة لإعلان المصفوفات والوصول إليها متطابقة، باستثناء أن لغة C# قد أضافت صيغة لإعلان المصفوفات متعددة الأبعاد ومعالجتها.

جافاسي شارب
المصفوفات هي تخصصات مباشرة ضمنية للكائن Object . وهي غير موحدة مع أنواع المجموعات.المصفوفات في لغة C# هي تخصصات ضمنية للفئة System.Arrayالتي تنفذ العديد من واجهات المجموعات .
المصفوفات والمجموعات منفصلة تمامًا ولا يوجد أي توحيد بينهما. لا يمكن تمرير المصفوفات في المواضع التي يُتوقع فيها تمرير التسلسلات أو المجموعات (مع أنه يمكن تغليفها باستخدام Arrays.asList).يمكن تمرير المصفوفات في الحالات التي يُتوقع فيها تمرير التسلسلات ( IEnumerable ) أو واجهات المجموعات/القوائم . مع ذلك، فإن عمليات المجموعات التي تُغير عدد العناصر (الإدراج/الإضافة/الحذف) ستُسبب استثناءات لأن هذه العمليات غير مدعومة من قِبل المصفوفات.
تقبل عبارة for إما المصفوفات أو الكائنات القابلة للتكرار . جميع المجموعات تُنفذ واجهة Iterable . هذا يعني أنه يمكن استخدام نفس الصيغة المختصرة في حلقات for.تُكرر عبارة foreach المرور عبر تسلسل باستخدام تطبيق محدد لطريقة GetEnumerator ، والتي تُنفذ عادةً من خلال واجهة IEnumerable . [ 36 ] ولأن المصفوفات تُنفذ هذه الواجهات ضمنيًا دائمًا، فإن الحلقة ستمر عبر المصفوفات أيضًا.IEnumerable<T>
في كلتا اللغتين، تكون مصفوفات أنواع المراجع متغيرة. هذا يعني أنه String[]يمكن إسناد قيمة إلى مصفوفة لمتغيرات من النوع `Object` Object[]، لأن `String` هو نوع خاص من ` Object` (قابل للإسناد إليه) . في كلتا اللغتين، تُجري المصفوفات فحصًا للنوع عند إدخال قيم جديدة، لأن سلامة النوع ستتأثر سلبًا في حال عدم إجراء هذا الفحص. وهذا يختلف عن كيفية تنفيذ المجموعات العامة في كلتا اللغتين.
لا توجد مصفوفات متعددة الأبعاد (مصفوفات مستطيلة)، ولكن توجد مصفوفات من المراجع إلى المصفوفات ( مصفوفات غير منتظمة ).المصفوفات متعددة الأبعاد (المصفوفات المستطيلة)، ومصفوفات المراجع إلى المصفوفات ( المصفوفات المتعرجة ).
لا يمكن تغيير حجم المصفوفات (على الرغم من أن استخدام هذه System.arraycopy()الطريقة يسمح بتغيير حجم المصفوفة على عدة خطوات)يمكن تغيير حجم المصفوفات مع الحفاظ على القيم الموجودة باستخدام Array.Resize()طريقة المصفوفة الثابتة (ولكن هذا قد يُرجع مصفوفة جديدة).
تم تنفيذه كتحديث للمكتبة، حيثjava.util أضاف ميزات إضافية، مثل هياكل البيانات كالمجموعات والمجموعات المرتبطة، ويحتوي على عدة خوارزميات لمعالجة عناصر المجموعة، مثل إيجاد أكبر عنصر بناءً على Comparator<T>كائن معين، وإيجاد أصغر عنصر، وإيجاد القوائم الفرعية داخل قائمة، وعكس محتويات قائمة، وخلط محتويات قائمة، وإنشاء نسخ غير قابلة للتغيير من مجموعة، وإجراء عمليات الفرز، وإجراء عمليات البحث الثنائي. [ 37 ]يتألف إطار عمل مجموعات C# من فئات من مساحات الأسماء System.Collectionsو مع العديد من الواجهاتSystem.Collections.Generic المفيدة ، والفئات المجردة، وهياكل البيانات. [ 38 ] أضافت NET 3.5 مساحة اسم تحتوي على طرق توسيع متنوعة للاستعلام عن المجموعات، مثل Aggregate و All و Average و Distinct و Join و Union وغيرها الكثير. تُسمى الاستعلامات التي تستخدم هذه الطرق استعلام اللغة المتكاملة (LINQ).System.Linq

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

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

تتميز كلتا اللغتين بمجموعة واسعة من أنواع المجموعات التي تشمل أنواعًا مختلفة مرتبة وغير مرتبة من القوائم والخرائط/القواميس والمجموعات وما إلى ذلك.

المجموعات

توفر لغة C# طريقتين مختلفتين لإنشاء أنواع الصفوف (المعروفة أيضًا بأنواع المنتج ). الأولى هي عبر System.Tupleالفئات، وهي أنواع مرجعية غير قابلة للتغيير توفرها واجهة برمجة تطبيقات إطار العمل (بدءًا من .NET Framework 4.0) لإنشاء أنواع صفوف عامة. [ 12 ] وقد تم استبدال هذه الطريقة الأولى فعليًا بالطريقة الثانية، وهي System.ValueTupleالبنى، وهي أنواع قيم قابلة للتغيير توفرها واجهة برمجة تطبيقات إطار العمل (بدءًا من .NET Framework 4.7). [ 13 ]

على الرغم من تشابه الطريقتين ظاهريًا، إلا أنهما تختلفان اختلافًا ملحوظًا في عدة جوانب. فأنواع ValueTuple هي أنواع قيم، لذا فهي تشغل مساحة ذاكرة أقل؛ كما أنها تعرض محتوياتها كحقول قابلة للتغيير، مقارنةً بخصائص Tuple غير القابلة للتغيير . وأخيرًا، منذ إصدار C# 7.0، تدعم اللغة بناء الجملة الأصلي لإنشاء وتفكيك ومعالجة tuples ككائنات ValueTuple ؛ وهذا يتيح أيضًا إعادة تسمية حقول tuples بشكل عشوائي (على عكس Tuple ، حيث تُسمى الحقول دائمًا Item1 و Item2 وما إلى ذلك ).

لا توفر لغة جافا أنواع البيانات الثنائية (tuple) كجزء من لغتها أو واجهة برمجة التطبيقات القياسية الخاصة بها؛ توجد العديد من المكتبات الخارجية التي توفر أنواع البيانات الثنائية، [ 39 ] ولكنها جميعًا متشابهة بالضرورة مع System.Tupleفئات C#. بالمقارنة مع أنواع ValueTuple في C# وبنيتها، فإن استخدامها أكثر تعقيدًا (إذ يتطلب استخدامًا صريحًا للدوال البانية أو دوال المصنع الثابتة لإنشائها، ويتطلب الوصول إلى كل عضو على حدة لتفكيكها، ولها أسماء ثابتة لعناصرها).

التعبيرات والمعاملات

التعبيرات والمعاملاتجافاسي شارب
عوامل التشغيل الحسابيةنعمنعم
عوامل التشغيل المنطقيةنعمنعم
عوامل التشغيل المنطقية الثنائيةنعمنعم
شرطينعمنعم
دمج السلاسلنعمنعم
استيفاء السلاسللانعم [ 40 ]
نصوص حرفية (هنا-)نعم [ 41 ]نعم [ 42 ]
طاقم العملنعمنعم
ملاكمةنعم؛ ضمنينعم؛ ضمني
فتح العلبةنعم؛ ضمنينعم؛ صريح
مشغلي الرافعاتلا؛ انظر java.util.Optionalنعم
التحكم في التدفق الزائدلانعم
تقييم دقيق للنقاط العائمةنعم؛ خيار الاشتراك/إلغاء الاشتراكنعم؛ الاشتراك [ 43 ]

التعبئة وفتح الصناديق

تسمح كلتا اللغتين بالتحويل التلقائي بين أنواع البيانات الأولية وأنواع البيانات المرجعية المقابلة.

في لغة C#، تُعتبر الأنواع الأولية أنواعًا فرعية من النوع Object. أما في لغة Java، فالأمر مختلف؛ إذ لا توجد علاقة محددة بين أي نوع أولي ونوع الغلاف المقابل له، باستثناء التحويل التلقائي بين الأنواع وفك التحويل، وهما بمثابة اختصار برمجي للتبادل بينهما. وقد تم ذلك عمدًا للحفاظ على التوافق مع الإصدارات السابقة من Java، حيث لم يكن التحويل التلقائي مسموحًا، وكان المبرمج يتعامل مع مجموعتين منفصلتين من الأنواع: الأنواع الأولية، وتسلسل أنواع الغلاف (المرجعية). [ 44 ]

يترتب على هذا الاختلاف النتائج التالية. أولاً، في لغة C#، يمكن للأنواع الأولية تعريف الدوال، مثل إعادة تعريف ToString()دالة الكائن. أما في لغة Java، فتُنجز هذه المهمة بواسطة فئات التغليف الأولية .

ثانيًا، في لغة جافا، يلزم إجراء تحويل نوع إضافي عند محاولة الوصول المباشر إلى قيمة أولية، لأنها لا تُحوّل تلقائيًا. يُحوّل التعبير قيمة عددية صحيحة إلى سلسلة نصية في جافا، بينما يُنفّذ التعبير نفسه في لغة سي شارب. والسبب في ذلك هو أن التعبير الأخير يُمثّل استدعاءً لمثيل القيمة الأولية 42 ، بينما يُمثّل التعبير الأول استدعاءً لمثيل كائن من النوع .((Integer)42).toString()42.ToString()java.lang.Integer

وأخيرًا، هناك فرق آخر يتمثل في أن لغة جافا تستخدم أنواعًا معلبة بشكل كبير في الأنواع العامة (انظر أدناه ).

البيانات

البياناتجافاسي شارب
الحلقاتنعمنعم
الشروطنعمنعم
التحكم في التدفقنعمنعم
تكليفنعمنعم
التحكم في الاستثناءاتنعمنعم
تعريف المتغيراتنعمنعم
استنتاج نوع المتغيرنعم [ 45 ]نعم
التخلص الحتمي (كتل ARM)نعمنعم

بناء الجملة

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

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

الكلمات المفتاحية والتوافق مع الإصدارات السابقة

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

تجنّب مصممو لغة جافا استخدام الكلمات المفتاحية الجديدة قدر الإمكان، مفضلين بدلاً من ذلك تقديم تراكيب نحوية جديدة لم تكن مسموحة سابقًا، أو إعادة استخدام الكلمات المفتاحية الموجودة في سياقات جديدة. وبهذه الطريقة، لم يُعرّضوا التوافق مع الإصدارات السابقة للخطر. مثال على ذلك هو كيفية توسيع حلقة for لقبول الأنواع القابلة للتكرار. ومثال على ذلك هو كيفية إعادة استخدام الكلمتين المفتاحيتين extends و super (خاصةً) لتحديد حدود الأنواع عند تقديم الأنواع العامة في جافا 1.5. في وقت ما (جافا 1.4)، تم تقديم كلمة مفتاحية جديدة assert لم تكن محجوزة ككلمة مفتاحية من قبل. كان من الممكن أن يؤدي ذلك إلى إبطال شيفرة برمجية كانت صالحة سابقًا، إذا كانت الشيفرة، على سبيل المثال، تستخدم assert كمعرّف. اختار المصممون معالجة هذه المشكلة بحل من أربع خطوات: 1) إدخال مفتاح تبديل للمترجم يشير إلى ما إذا كان يجب استخدام Java 1.4 أو أحدث، 2) وضع علامة assert ككلمة رئيسية فقط عند الترجمة باستخدام Java 1.4 أو أحدث، 3) استخدام الإصدار 1.3 افتراضيًا لتجنب جعل التعليمات البرمجية السابقة (غير المتوافقة مع الإصدار 1.4) غير صالحة، 4) إصدار تحذيرات، إذا تم استخدام الكلمة الرئيسية في وضع Java 1.3، للسماح بإجراء تغييرات في التعليمات البرمجية.

أدخل مصممو لغة C# العديد من الكلمات المفتاحية الجديدة منذ الإصدار الأول. ومع ذلك، فبدلاً من تعريف هذه الكلمات ككلمات مفتاحية عامة ، تم تعريفها ككلمات مفتاحية حساسة للسياق . هذا يعني أنه حتى عند إدخال الكلمتين المفتاحيتين partial و yield (من بين كلمات أخرى) في C# 2.0، يظل استخدام هاتين الكلمتين كمعرفات صحيحًا، إذ لا يوجد تعارض محتمل بين استخدامهما ككلمة مفتاحية واستخدامهما كمعرف، بالنظر إلى السياق. وبالتالي، فإن بنية C# الحالية متوافقة تمامًا مع الإصدارات السابقة من التعليمات البرمجية، بغض النظر عن إصدار اللغة المستخدم.

الكلمة المفتاحيةميزة، مثال على الاستخدام
مُحدد ، غير مُحددفي لغة C#، يمكن لكتل ​​العبارات أو التعبيرات التي تم فحصها تمكين التحقق من تجاوزات العمليات الحسابية في وقت التشغيل . [ 46 ]
احصل على ، اضبطتُنفذ لغة C# الخصائص كجزء من بناء الجملة للغة مع أدوات الوصول المقابلة لها الاختيارية get و set ، كبديل لأساليب الوصول المستخدمة في Java، والتي ليست ميزة لغوية ولكنها نمط برمجي يعتمد على اصطلاحات تسمية الأساليب.
انتقل إلىتدعم لغة C# الكلمة gotoالمفتاحية goto. قد يكون هذا مفيدًا في بعض الأحيان، على سبيل المثال لتنفيذ آلات الحالة المحدودة أو للتعليمات البرمجية المولدة ، ولكن يُنصح عادةً باستخدام طريقة أكثر تنظيمًا للتحكم في تدفق التعليمات البرمجية (انظر انتقادات عبارة goto ). لا تدعم لغة Java عبارة goto (مع العلم أن goto كلمة محجوزة). ومع ذلك، تدعم Java عبارات break و continue المُعَلَّمة ، والتي يمكن استخدامها في بعض الحالات بدلًا من عبارة goto .
switch ( color ) { case Color . Blue : Console . WriteLine ( "اللون أزرق" ); break ; case Color . DarkBlue : Console . WriteLine ( "اللون داكن" ); goto case Color . Blue ; // ... }
قفلفي لغة C#، الكلمة المفتاحية lock هي اختصار لمزامنة الوصول إلى كتلة من التعليمات البرمجية عبر الخيوط (باستخدام Monitor )، ملفوفة في كتلة try ... finally .
خارج ، مرجعتدعم لغة C# معلمات الإخراج والمعلمات المرجعية . تسمح هذه المعلمات بإرجاع قيم إخراج متعددة من دالة، أو تمرير القيم عن طريق المرجع.
strictfpكانت لغة جافا strictfpتضمن بقاء نتائج عمليات الفاصلة العائمة كما هي عبر المنصات؛ لم يعد هذا الأمر ذا صلة في JDK 17 وما بعده [ 47 ] .
يُحوّلفي لغة C#، تعمل عبارة switch أيضًا على السلاسل النصية والأنواع الطويلة. يُسمح بالتنفيذ المتتالي للعبارات الفارغة، ويمكن تنفيذه عبر عبارة 'goto case' للعبارات التي تحتوي على تعليمات برمجية. أما في لغة Java، فتعمل عبارة switch على السلاسل النصية (منذ Java 7 )، ولكنها لا تعمل على النوع الأولي الطويل ، وتنفذ التنفيذ المتتالي لجميع العبارات (باستثناء تلك التي تحتوي على ' break '). [ 48 ]
متزامنفي لغة جافا، الكلمة المفتاحية synchronized هي اختصار لمزامنة الوصول إلى كتلة من التعليمات البرمجية عبر الخيوط (باستخدام Monitor )، ملفوفة في كتلة try ... finally .
يرميتتطلب لغة جافا من كل دالة تعريف الاستثناءات المُدققة أو الفئات الأصلية للاستثناءات المُدققة التي يمكنها طرحها. كما يمكن لأي دالة تعريف الاستثناء غير المُدقق الذي تطرحه. أما لغة سي شارب فلا تحتوي على مثل هذه الصيغة.
استيراد java.io.IOException ؛public int readItem () throws IOException { // ... }
استخدامفي لغة C#، يؤدي استخدام "using " إلى تنفيذ طريقة Dispose (المنفذة عبر واجهة IDisposable ) للكائن المعلن عنه بعد تشغيل كتلة التعليمات البرمجية أو عند حدوث استثناء داخل كتلة التعليمات البرمجية.
// أنشئ ملفًا صغيرًا باسم "test.txt"، واكتب سلسلة نصية فيه، // ... ثم أغلقه (حتى في حالة حدوث استثناء) باستخدام ( StreamWriter file = new ( "test.txt" )) { file . Write ( "test" ); }

في Java SE 7 تمت إضافة بنية مماثلة [ 49 ] تسمى try-with-resources:

try ( BufferedReader br = new BufferedReader ( new FileReader ( path ))) { return br.readLine ( ) ; }

البرمجة الكائنية التوجه

تم تصميم كل من لغتي C# و Java من الصفر كلغات كائنية التوجه تستخدم الإرسال الديناميكي ، مع بنية مشابهة للغة C++ (التي بدورها مشتقة من C ). ومع ذلك، لا تُعد أي من اللغتين مجموعة شاملة للغة C أو C++.

توجيه الكائنجافاسي شارب
الصفوف الدراسيةإلزاميإلزامي
واجهاتنعمنعم
الفئات المجردةنعمنعم
مستويات إمكانية وصول الأعضاءعام، حزمة، محمي، خاصعام، داخلي، محمي، خاص، داخلي محمي
صفوف داخلية على مستوى الفصلنعمنعم
الفئات الداخلية على مستوى المثيلنعملا
الفئات المجهولة على مستوى البيان (المحلية)نعمنعم؛ ولكن بدون أساليب
فصول جزئيةلا؛ مكتبة طرف ثالث [ 50 ]نعم
الفئات المجهولة الضمنية (المستنتجة)لا؛ ليس ضرورياًنعم [ 51 ]
الإهمال / التقادمنعمنعم
إصدار مُحمّل بشكل زائدبعضنعم
يمكن للأنواع المُعدّدة (Enums) تطبيق الواجهات (Interfaces) .نعملا
ملكياتلانعم
الفعالياتمقدمة من المكتبات القياسيةميزة اللغة المدمجة
إرهاق المشغللانعم
الفهرسةلانعم
التحويلات الضمنيةلا؛ ولكن انظر إلى نظام نقل الحركة التلقائينعم
التحويلات الصريحةنعمنعم

فئة جزئية

تتيح لغة C# تقسيم تعريف الصنف إلى عدة ملفات مصدرية باستخدام ميزة تُسمى الأصناف الجزئية . يجب تمييز كل جزء بالكلمة المفتاحية partial . يجب تقديم جميع الأجزاء للمترجم كجزء من عملية ترجمة واحدة. يمكن للأجزاء الإشارة إلى أعضاء من أجزاء أخرى، كما يمكنها تطبيق الواجهات، ويمكن لأحد الأجزاء تعريف صنف أساسي. تُعد هذه الميزة مفيدة في سيناريوهات توليد التعليمات البرمجية (مثل تصميم واجهة المستخدم )، حيث يمكن لمولد التعليمات البرمجية تزويد المطور بجزء، بينما يُزوّد ​​المطور بجزء آخر ليتم تجميعهما معًا. وبالتالي، يستطيع المطور تعديل الجزء الخاص به دون خطر استبداله بواسطة مولد التعليمات البرمجية لاحقًا. على عكس آلية توسيع الأصناف، يسمح الصنف الجزئي بوجود تبعيات دائرية بين أجزائه، حيث يُضمن حلها في وقت الترجمة. لا يوجد مفهوم مماثل في لغة Java.

الفصول الداخلية والمحلية

تسمح كلتا اللغتين بالفئات الداخلية ، حيث تُعرَّف فئة ما معجميًا داخل فئة أخرى. ومع ذلك، فإن لهذه الفئات الداخلية دلالات مختلفة تمامًا في كل لغة .

في لغة جافا، ما لم يُصرَّح عن الفئة الداخلية بأنها ثابتة (static) ، فإن أي إشارة إلى نسخة من فئة داخلية تحمل معها إشارة إلى الفئة الخارجية. ونتيجةً لذلك، يمكن للكود الموجود في الفئة الداخلية الوصول إلى كلٍّ من الأعضاء الثابتة وغير الثابتة للفئة الخارجية. لإنشاء نسخة من فئة داخلية غير ثابتة، يجب تسمية نسخة الفئة الخارجية المُحيطة بها. [ 52 ] يتم ذلك باستخدام عامل التشغيل الجديد `new` الذي تم تقديمه في JDK 1.3 . يمكن تطبيق هذا في أي فئة تحتوي على إشارة إلى نسخة من الفئة الخارجية.outerClassInstance.new Outer.InnerClass()

في لغة C#، يُعتبر الصنف الداخلي مُرادفًا للصنف العادي من حيث المفهوم. بمعنى آخر، يعمل الصنف الخارجي كمساحة اسم فقط. وبالتالي، لا يمكن للتعليمات البرمجية في الصنف الداخلي الوصول إلى الأعضاء غير الثابتة في الصنف الخارجي إلا من خلال مرجع صريح إلى نسخة من الصنف الخارجي. يمكن للمبرمجين تعريف الصنف الداخلي كصنف خاص (private) بحيث يقتصر الوصول إليه على الصنف الخارجي فقط.

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

توفر لغة C# ميزة تُسمى الأنواع/الفئات المجهولة ، لكنها تختلف تمامًا عن مفهوم Java الذي يحمل نفس الاسم. فهي تُمكّن المبرمج من إنشاء كائن من فئة ما بمجرد تحديد مجموعة من أسماء خصائص الفئة، وتعبير لتهيئة كل خاصية. ويتم استنتاج أنواع الخصائص من أنواع تلك التعبيرات. وتُشتق هذه الفئات المُعلنة ضمنيًا مباشرةً من الكائن `object` .

حدث

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

انظر هنا للحصول على معلومات حول كيفية تنفيذ الأحداث في لغة جافا.

التحميل الزائد للمشغل والتحويلات

يُعدّ تحميل المعاملات الزائد والتحويلات المُعرّفة من قِبل المستخدم ميزتين منفصلتين تهدفان إلى تمكين الأنواع الجديدة من أن تُصبح عناصر أساسية في نظام الأنواع. وباستخدام هاتين الميزتين في لغة C#، تم دمج أنواع مثل Complex و decimal بحيث تعمل المعاملات المعتادة كالجمع والضرب مع هذه الأنواع الجديدة. وعلى عكس لغة C++، تُقيّد لغة C# استخدام تحميل المعاملات الزائد، إذ تمنعه ​​للمعاملات new و و و و وأي صيغ مُختلفة من العبارات المركبة مثل . ولكن المعاملات المركبة ستستدعي المعاملات البسيطة المُحمّلة، مثل استدعاء و . [ 53 ]( )||&&=+=-=-=

لا تتضمن لغة جافا خاصية تحميل المعاملات الزائدة، ولا التحويلات المخصصة لمنع إساءة استخدام هذه الخاصية وللحفاظ على بساطة اللغة. [ 54 ]

فهرسة

تتضمن لغة C# أيضًا الفهارس التي يمكن اعتبارها حالة خاصة من تحميل المعاملات الزائد (مثل لغة C++ operator[])، أو خصائص get / set المُعَلمة . الفهرس هو خاصية مُسماة تستخدم مُعاملًا واحدًا أو أكثر (فهرسًا)؛ ويمكن أن تكون الفهارس كائنات من أي نوع.this[]

myList [ 4 ] = 5 ; string name = xmlNode.Attributes [ "name" ] ; orders = customerMap [ theCustomer ] ;

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

الحقول والتهيئة

الحقول والتهيئةجافاسي شارب
الحقولنعمنعم
الثوابتنعمنعم؛ ولكن لا يوجد دعم للمعاملات الثابتة التي تم تمريرها [ 55 ]
المُنشئات الثابتة (للفئات)نعمنعم
مُنشئات النسخنعمنعم
المُنهيات/المُدمراتنعمنعم
مُهيئات المثيلنعملا؛ يمكن محاكاتها باستخدام مُنشئ النسخة
تهيئة الكائنمن الأسفل إلى الأعلى (الحقول والمنشئات)من أعلى إلى أسفل (الحقول)؛ من أسفل إلى أعلى (المنشئات)
مُهيئات الكائناتنعمنعم
مُهيئات المجموعةطرق الوسائط المتغيرة الثابتةنعم
مُهيئات المصفوفةنعمنعم

تهيئة الكائن

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

تقوم لغة C# بتهيئة حقول الكائن بالترتيب التالي عند إنشاء كائن:

  1. الحقول الساكنة المشتقة
  2. المُنشئ الثابت المشتق
  3. حقول النسخة المشتقة
  4. الحقول الثابتة الأساسية
  5. المُنشئ الثابت الأساسي
  6. حقول المثيل الأساسي
  7. مُنشئ النسخة الأساسية
  8. مُنشئ النسخة المشتقة

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

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

في لغة جافا، يكون ترتيب التهيئة كما يلي:

  1. استدعاء مُنشئ آخر (إما من فئة الكائن أو من الفئة الأصلية للكائن)
  2. مُهيئات متغيرات النسخة ومُهيئات النسخة (بالترتيب الذي تظهر به في شفرة المصدر)
  3. جسم المُنشئ

كما هو الحال في لغة C#، يُنشأ كائن جديد باستدعاء مُنشئ مُحدد. داخل المُنشئ، قد تكون العبارة الأولى استدعاءً لمُنشئ آخر. إذا حُذف هذا، يُضيف المُصرّف ضمنيًا استدعاء المُنشئ بدون وسائط للفئة الأصلية. وإلا، يُمكن استدعاء مُنشئ آخر مُحمّل بشكل زائد لفئة الكائن صراحةً، أو استدعاء مُنشئ الفئة الأصلية. في الحالة الأولى، سيستدعي المُنشئ المُستدعى مُنشئًا آخر (إما لفئة الكائن أو لفئته الفرعية)، وتنتهي السلسلة عاجلاً أم آجلاً باستدعاء أحد مُنشئات الفئة الأصلية.

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

وأخيرًا، يتم تنفيذ جسم الدالة البانية. وهذا يضمن الترتيب الصحيح للتهيئة، أي أن حقول الفئة الأساسية تنتهي من التهيئة قبل أن تبدأ تهيئة حقول فئة الكائن.

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

التخلص من الموارد

تستخدم كلتا اللغتين بشكل أساسي آلية جمع البيانات المهملة لاستعادة موارد الذاكرة، بدلاً من تحرير الذاكرة بشكل صريح. في كلتا الحالتين، إذا كان الكائن يحتوي على موارد من أنواع مختلفة غير الذاكرة، مثل مؤشرات الملفات والموارد الرسومية، وما إلى ذلك، فيجب إخطاره صراحةً عندما يتوقف التطبيق عن استخدامه. توفر كل من C# و Java واجهات لهذا النوع من التخلص الحتمي ، كما تتميز كلتاهما (منذ Java 7) بعبارات إدارة موارد تلقائية تستدعي تلقائيًا دوال التخلص/الإغلاق في تلك الواجهات.

طُرق

الأساليب والخصائصجافاسي شارب
الاستيرادات الثابتةنعمنعم [ 56 ]
الأساليب الافتراضيةافتراضي افتراضيًاغير افتراضي افتراضياً
خلاصةنعمنعم
ختمنعمنعم
تنفيذ الواجهة الصريحالطرق الافتراضيةنعم [ 57 ]
معلمات القيمة (الإدخال)نعمنعم
معلمات مرجعية (إدخال/إخراج)لانعم
معلمات الإخراجلانعم
المعاملات الثابتة (غير القابلة للتغيير)نعم؛ المعايير النهائيةنعم [ 58 ]
الأساليب المتغيرةنعمنعم
الوسائط الاختياريةلا؛ [ 59 ] بدلاً من ذلك، يتم استخدام التحميل الزائد للأساليب أو الوسائط المتغيرة.نعم
الوسائط المسماةنعم؛ مع التعليقات التوضيحيةنعم
طرق المولدلا؛ ولكن انظر إلى واجهة برمجة تطبيقات البثنعم
طرق الامتداد/الافتراضيةنعمنعم
الأساليب الشرطيةلانعم
الطرق الجزئيةلانعم

أساليب التوسيع والأساليب الافتراضية

باستخدام مُعرِّف this الخاص على المُعامل الأول للدالة، تسمح لغة C# للدالة بالعمل كما لو كانت دالة عضو من نوع المُعامل الأول. هذا الامتداد للفئة الخارجية هو امتداد نحوي بحت. يجب تعريف دالة الامتداد على أنها ثابتة (static ) وتعريفها داخل فئة ثابتة تمامًا. يجب أن تلتزم الدالة بأي قيود وصول للأعضاء مثل أي دالة أخرى خارج الفئة؛ وبالتالي، لا يمكن للدوال الثابتة أن تُخلّ بتغليف الكائنات. [ 60 ] [ 61 ] يكون "الامتداد" نشطًا فقط ضمن النطاقات التي تم فيها استيراد مساحة اسم الفئة المضيفة الثابتة.

منذ إصدار Java 8، توفر Java ميزة مشابهة تُسمى " الأساليب الافتراضية" ، وهي أساليب مُعرّفة في الواجهات. على عكس أساليب الإضافة في C#، فإن الأساليب الافتراضية في Java هي أساليب خاصة بالواجهة التي تُعرّفها. تعريف الأساليب الافتراضية في الفئات التي تُنفّذ الواجهة اختياري: إذا لم تُعرّف الفئة الأسلوب، يُستخدم التعريف الافتراضي بدلاً من ذلك.

تسمح كل من طرق الإضافة في لغة C# وطرق Java الافتراضية للفئة بتجاوز التنفيذ الافتراضي لطريقة الإضافة/الطريقة الافتراضية، على التوالي. في كلتا اللغتين، يتم تحقيق هذا التجاوز عن طريق تعريف طريقة في الفئة تستخدم تنفيذًا بديلًا للطريقة الأصلية.

تُحدد قواعد نطاق C# أنه إذا وُجدت دالة مطابقة في فئة ما، فإنها تُعطى الأولوية على دالة الإضافة المطابقة. في Java، يُفترض أن أي فئة مُعلنة لتنفيذ واجهة ذات دالة افتراضية تحتوي على تطبيقات الدوال الافتراضية، ما لم تُنفذ الفئة الدالة بنفسها.

الطرق الجزئية

فيما يتعلق بالفئات الجزئية، تسمح لغة C# بتحديد الدوال الجزئية داخل الفئات الجزئية. الدالة الجزئية هي تعريف مُتعمّد لدالة مع قيود مُحددة على توقيعها. تضمن هذه القيود أنه في حال عدم تعريف الدالة من قِبل أي جزء من أجزاء الفئة، يُمكن حذف الدالة وجميع استدعاءاتها بأمان. [ 62 ] تُتيح هذه الميزة للبرنامج توفير عدد كبير من نقاط الاعتراض (مثل نمط تصميم GoF للدوال القالبية ) دون أي تكلفة إضافية أثناء التشغيل، إذا لم تكن نقاط التمديد هذه مُستخدمة من قِبل أي جزء آخر من أجزاء الفئة أثناء الترجمة. لا يوجد مفهوم مُماثل في لغة Java.

الأساليب الافتراضية

في لغة C#، تكون الدوال غير افتراضية افتراضيًا، ويجب تعريفها افتراضيًا بشكل صريح إذا لزم الأمر. أما في لغة Java، فجميع الدوال غير الثابتة وغير الخاصة افتراضية. يضمن الوضع الافتراضي استدعاء آخر نسخة مُعاد تعريفها للدالة دائمًا، ولكنه يُضيف تكلفة زمنية عند الاستدعاء، حيث لا يمكن تضمين هذه الاستدعاءات عادةً ، وتتطلب استدعاءً غير مباشر عبر جدول الدوال الافتراضية . مع ذلك، تُتيح بعض تطبيقات JVM، بما في ذلك تطبيق Oracle المرجعي، تضمين الدوال الافتراضية الأكثر شيوعًا.

تُعتبر دوال جافا افتراضية افتراضياً (مع إمكانية إغلاقها باستخدام المُعدِّل `final` لمنع إعادة تعريفها). لا توجد طريقة للسماح للفئات المشتقة بتعريف دالة جديدة غير مرتبطة بنفس الاسم.

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

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

للتخفيف من هذه المشكلة، يشترط C# تحديد الكلمة المفتاحية override إذا كان الهدف من دالة ما هو تجاوز دالة موروثة . وإلا، ستخفي الدالة الموروثة. في حال عدم وجود هذه الكلمة، يُصدر المُصرّف تحذيرًا بهذا الشأن، ويمكن تجاهله بتحديد الكلمة المفتاحية new . هذا يتجنب المشكلة التي قد تنشأ عند توسيع فئة أساسية بدالة غير خاصة (أي جزء موروث من مساحة الاسم) يكون توقيعها مُستخدمًا بالفعل من قِبل فئة مشتقة. لدى Java فحص مُصرّف مُشابه في شكل تعليق توضيحي للدالة، ولكنه ليس إلزاميًا، وفي حال عدم وجوده، لن تُضيف مُعظم المُصرّفات تعليقًا (ولكن سيتم تجاوز الدالة).@Override

المعاملات الثابتة/غير القابلة للتغيير

في لغة جافا، يُمكن منع إعادة تعيين قيمة متغير محلي أو مُعامل دالة باستخدام الكلمة المفتاحية `const`. يؤدي تطبيق هذه الكلمة المفتاحية على متغير من نوع بيانات أولي إلى جعله غير قابل للتغيير. مع ذلك، فإن تطبيقها على متغير من نوع مرجعي يمنع فقط تعيين قيمة كائن آخر له، ولا يمنع تغيير البيانات التي يحتويها هذا الكائن. بدءًا من لغة C# 7 ، يُمكن منع إعادة تعيين قيمة مُعامل دالة باستخدام الكلمة المفتاحية `in` ، ولكن لا يُمكن استخدام هذه الكلمة المفتاحية على المتغيرات المحلية. كما هو الحال في جافا، فإن تطبيق ` in` على مُعامل يمنع فقط إعادة تعيين قيمة هذا المُعامل إلى قيمة مختلفة، ويبقى من الممكن تغيير البيانات التي يحتويها الكائن. [ 63 ]finalfinal

جافاسي شارب
استيراد java.util.List ;int addOne ( final int x ) { x ++ ; // خطأ: لا يمكن إعادة تعيين متغير نهائي // return x ; }List <Integer> addOne ( final List <Integer> list ) { list.add ( 1 ) ; // صحيح: لا يزال من الممكن تعديل متغير نهائي (من نوع مرجعي ) // return list ; }
باستخدام System.Collections.Generic ؛public int AddOne ( in int x ) { x ++ ; // خطأ: لا يمكن إعادة تعيين قيمة لمعامل للقراءة فقط return x ; }public List <int> AddOne ( in List <int> list ) { list.Add ( 1 ) ; // صحيح: لا يزال من الممكن تعديل // مُعامل للقراءة فقط ( نوع مرجعي) return list ; }

لا تدعم كلتا اللغتين الميزة الأساسية لـ const-healthness الموجودة في C / C++ ، والتي تجعل الطريقة ثابتة.

تُعرّف لغة جافا كلمة "constant" بشكلٍ اعتباطي كحقل . وكعرفٍ شائع، تُكتب أسماء هذه المتغيرات بأحرف كبيرة فقط، وتُفصل الكلمات بشرطة سفلية، لكن لغة جافا لا تُصرّ على ذلك. لا يُعتبر المُعامل الذي قيمته صفر ثابتًا، مع أنه قد يكون كذلك في حالة نوع بيانات أولي أو فئة غير قابلة للتغيير ، مثل .staticfinalfinalString

طرق المولد

يمكن تنفيذ أي دالة في لغة C# تُعرّف على أنها تُرجع IEnumerable أو IEnumerator أو الإصدارات العامة لهذه الواجهات باستخدام صيغة yield . يُعدّ هذا شكلاً من أشكال الاستمرارية المحدودة التي يُنشئها المُصرّف، ويمكنه تقليل حجم الكود اللازم لاجتياز أو إنشاء المتتاليات بشكل كبير، على الرغم من أن هذا الكود يُنشئه المُصرّف فقط. كما يمكن استخدام هذه الميزة لتنفيذ المتتاليات اللانهائية، مثل متتالية أعداد فيبوناتشي .

لا تحتوي لغة جافا على ميزة مكافئة. بدلاً من ذلك، تُعرَّف المولدات عادةً بتوفير تطبيق متخصص لمجموعة معروفة أو واجهة قابلة للتكرار، والتي ستحسب كل عنصر عند الطلب. لكي يُستخدم مثل هذا المولد في عبارة for each ، يجب أن يُطبِّق الواجهة java.lang.Iterable.

انظر أيضًا مثال متتالية فيبوناتشي أدناه.

تنفيذ الواجهة الصريح

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

في كلتا اللغتين، إذا تم تحديد دالة (أو خاصية في C#) بنفس الاسم والتوقيع في واجهات متعددة، فسيحدث تعارض بين عناصرها عند تصميم فئة تُنفذ تلك الواجهات. يُنفذ التطبيق افتراضيًا دالة مشتركة لجميع الواجهات. إذا لزم وجود تطبيقات منفصلة (لأن الدوال تخدم أغراضًا مختلفة، أو لأن القيم المُعادة تختلف بين الواجهات)، فإن تطبيق الواجهة الصريح في C# سيحل المشكلة، مع السماح بنتائج مختلفة لنفس الدالة، اعتمادًا على نوع الكائن المُستخدم. في Java، لا توجد طريقة لحل هذه المشكلة سوى إعادة هيكلة واحدة أو أكثر من الواجهات لتجنب تعارض الأسماء. [ 57 ]

معلمات مرجعية (داخلية/خارجية)

في لغة جافا، تُمرَّر وسائط الأنواع الأولية (مثل int وdouble) إلى الدوال بالقيمة، بينما تُمرَّر الكائنات بالمرجع. هذا يعني أن الدالة تعمل على نسخ من الأنواع الأولية المُمرَّرة إليها بدلاً من المتغيرات الأصلية. على النقيض من ذلك، يمكن تغيير الكائنات الأصلية في بعض الحالات. في المثال التالي، لم يتغير الكائن String، بينما تغير الكائن من الفئة 'a'.

في لغة C#، يُمكن فرض مرجع باستخدام الكلمة المفتاحية ref ، على غرار لغة C++، وإلى حد ما، لغة C. تُعدّ هذه الميزة في C# مفيدةً للغاية عند الرغبة في إنشاء دالة تُعيد أكثر من كائن واحد. أما في لغة Java، فإن محاولة إعادة قيم متعددة من دالة واحدة غير مدعومة إلا باستخدام غلاف، يُسمى في هذه الحالة "Ref". [ 64 ]

جافاسي شارب
class PassByRefTest {class Ref <T> { T val ; Ref ( T val ) { this.val = val ; } } void changeMe ( Ref <String> s ) { s.val = " تم التغيير " ; }void swap ( Ref < Integer > x , Ref < Integer > y ) { int temp = x . val ; x . val = y . val ; y . val = temp ; }void main () { var a = new Ref < Integer > ( 5 ); var b = new Ref < Integer > ( 10 ); var s = new Ref < String > ( "still unchanged" ); swap ( a , b ); changeMe ( s );System.out.printf ( " a = % d , b = %d, s = % s %n " , a.val , b.val , s.val ) ; } }
باستخدام النظام ؛class PassByRefTest { public static void ChangeMe ( out string s ) { s = "Changed" ; }public static void Swap ( ref int x , ref int y ) { int temp = x ;x = y ; y = temp ; }public static void Main ( string [] args ) { int a = 5 ; int b = 10 ; string s = "still unchanged" ;تبديل ( المرجع أ ، المرجع ب تغيير ( الناتج س Console.WriteLine ( $"a = {a}, b = { b}, s = { s}" ); } }
a = 10, b = 5, s = Changeda = 10, b = 5, s = Changed

الاستثناءات

الاستثناءاتجافاسي شارب
الاستثناءات التي تم التحقق منهانعملا
حاول-أمسك-أخيراًنعمنعم
مرشحات الاستثناءلانعم [ 65 ]

الاستثناءات التي تم التحقق منها

تدعم لغة جافا الاستثناءات المُدققة (إلى جانب الاستثناءات غير المُدققة). بينما تدعم لغة سي شارب الاستثناءات غير المُدققة فقط. تُجبر الاستثناءات المُدققة المبرمج إما على تعريف الاستثناء المطروح داخل دالة، أو على التقاطه باستخدام عبارة try-catch .

يمكن أن تُشجع الاستثناءات المُدققة على ممارسات البرمجة الجيدة، إذ تضمن معالجة جميع الأخطاء. مع ذلك، يرى أندرس هيلسبرغ ، كبير مهندسي لغة C#، أنها كانت إلى حد ما تجربة في جافا، وأنه لم يثبت جدواها إلا في برامج تجريبية صغيرة. [ 66 ] [ 67 ]

من الانتقادات الموجهة إلى الاستثناءات المُدققة أنها تُشجع المبرمجين على استخدام كتلة catch فارغة [ 68 ] ، والتي تتجاهل الاستثناءات دون تنبيه، بدلاً من السماح لها بالانتقال إلى روتين معالجة استثناءات أعلى مستوى. مع ذلك، في بعض الحالات، يُمكن تطبيق تسلسل الاستثناءات بدلاً من ذلك، عن طريق إعادة طرح الاستثناء في استثناء مُغلِّف. على سبيل المثال، إذا تم تغيير كائن للوصول إلى قاعدة بيانات بدلاً من ملف، يُمكن التقاط استثناء وإعادة طرحه كاستثناء ، لأن المُستدعي قد لا يحتاج إلى معرفة تفاصيل عمل الكائن.catch(Exceptione){}SQLExceptionIOException

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

حاول-أمسك-أخيراً

توجد أيضًا اختلافات بين اللغتين في معالجة try-finallyالعبارة. يُنفَّذ جزء "finally " دائمًا، حتى لو احتوى جزء "try " على عبارات تمرير تحكم مثل "throw" أو "return" . في جافا، قد يؤدي هذا إلى سلوك غير متوقع، إذا خرج جزء "try " من عبارة "return" بقيمة معينة، ثم خرج جزء "finally " الذي يُنفَّذ بعد ذلك من عبارة "return" بقيمة مختلفة. تحل لغة C# هذه المشكلة بمنع أي عبارات تمرير تحكم مثل "return" أو "break" في جزء "finally" .

من الأسباب الشائعة لاستخدام try-finallyالكتل البرمجية حماية شيفرة إدارة الموارد، مما يضمن تحرير الموارد الثمينة في كتلة `finally`. تتميز لغة C# باستخدام عبارة `using` كاختصار نحوي لهذا السيناريو الشائع، حيث يتم استدعاء دالة الكائن المُستخدم في ` using` دائمًا.Dispose()

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

class Foo { Exception up = new Exception (); int foo () throws Exception { throw up ; } }

سيحتوي الاستثناء المذكور في العبارة أعلاه دائمًا على تتبع مكدس المُنشئ، بغض النظر عن عدد مرات استدعاء الدالة foo. أما في لغة C#، فيتم إنشاء تتبع المكدس لحظة تنفيذ الأمر "throw".

class Foo { Exception e = new ();int Foo () { try { throw e ; } catch ( Exception e ) { throw ; } } }

في الكود أعلاه، سيحتوي الاستثناء على تتبع المكدس لسطر الرمي الأول. عند التقاط استثناء، هناك خياران في حال إعادة رمي الاستثناء: الخيار الأول هو إعادة رمي الاستثناء الأصلي مع تتبع المكدس الأصلي، بينما الخيار الثاني هو إنشاء تتبع مكدس جديد.throw e

الكتل النهائية

تسمح لغة جافا بخروج مسار التحكم من كتلة `finally` في عبارة `try` ، بغض النظر عن طريقة الدخول إليها. قد يؤدي هذا إلى إنهاء عبارة تحكم أخرى (مثل `return` ) أثناء التنفيذ. على سبيل المثال:

int foo () { try { return 0 ; } finally { return 1 ; } }

في الكود أعلاه، تتسبب عبارة الإرجاع داخل كتلة try في خروج التحكم منها، وبالتالي يتم تنفيذ كتلة finally قبل حدوث الإرجاع الفعلي. مع ذلك، تقوم كتلة finally نفسها بتنفيذ إرجاع. لذا، لا يتم تنفيذ الإرجاع الأصلي الذي تسبب في دخولها، وتُرجع الدالة أعلاه القيمة 1 بدلاً من 0. بعبارة أخرى، تحاول الدالة إرجاع 0 ولكنها تُرجع في النهاية 1.

لا تسمح لغة C# بأي عبارات تسمح بخروج مسار التحكم من كتلة finally قبل الأوان، باستثناء عبارة throw . وبالتحديد، لا يُسمح باستخدام عبارة return إطلاقًا، ولا يُسمح باستخدام عبارة goto إذا كان الهدف خارج كتلة finally ، ولا يُسمح باستخدام عبارة continue أو break إذا كانت أقرب حلقة محيطة خارج كتلة finally .

الأدوية الجنيسة

في مجال التعميم، تظهر اللغتان تشابهاً نحوياً سطحياً، لكنهما تختلفان اختلافاً عميقاً في جوهرهما.

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

محو النوع مقابل الأنواع العامة المُجسَّدة

تُعدّ الأنواع العامة في جافا بنيةً لغويةً بحتة، إذ تُنفَّذ فقط في المُصرِّف. تتضمن ملفات الفئات المُولَّدة توقيعات الأنواع العامة فقط في صورة بيانات وصفية (مما يسمح للمُصرِّف بتجميع فئات جديدة بناءً عليها). لا يمتلك وقت التشغيل أي معرفة بنظام الأنواع العامة؛ فالأنواع العامة ليست جزءًا من آلة جافا الافتراضية (JVM). بدلاً من ذلك، تُحوَّل فئات وأساليب الأنواع العامة أثناء التجميع عبر عملية تُسمى محو النوع . خلال هذه العملية، يستبدل المُصرِّف جميع الأنواع العامة بنسخها الأصلية ، ويُدرج عمليات التحويل/التحقق المناسبة في كود العميل حيث يُستخدم النوع وأساليبه. لن يحتوي رمز البايت الناتج على أي مراجع لأي أنواع أو معلمات عامة (انظر أيضًا الأنواع العامة في جافا ).

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

تعتمد لغة C# على دعم الأنواع العامة من نظام التنفيذ الافتراضي، أي أنها ليست مجرد ميزة لغوية. اللغة هي مجرد واجهة أمامية لدعم الأنواع العامة عبر اللغات في بيئة CLR . أثناء عملية الترجمة، يتم التحقق من صحة الأنواع العامة، ولكن يتم تأجيل توليد الكود اللازم لتنفيذها إلى وقت تحميل الفئة. يتم تجميع كود العميل (الكود الذي يستدعي الطرق/الخصائص العامة) بالكامل، ويمكنه افتراض أن الأنواع العامة آمنة من حيث النوع. يُسمى هذا التجسيد . في وقت التشغيل، عند مصادفة مجموعة فريدة من معلمات النوع لفئة/طريقة/مفوض عام لأول مرة، يقوم مُحمِّل/مُدقِّق الفئات بتوليد واصف فئة ملموس وإنشاء تطبيقات للطرق. أثناء توليد تطبيقات الطرق، تُعتبر جميع أنواع المراجع نوعًا واحدًا، حيث يمكن لأنواع المراجع مشاركة نفس التطبيقات بأمان. هذا فقط لغرض تنفيذ الكود. ستظل مجموعات أنواع المراجع المختلفة تحتوي على واصفات أنواع فريدة؛ وستشير جداول الطرق الخاصة بها إلى نفس الكود.

توضح القائمة التالية بعض الاختلافات بين لغتي Java و C# عند إدارة الأنواع العامة. وهي ليست شاملة: [ 72 ]

جافاسي شارب
تُضاف عمليات التحقق من الأنواع والتحويلات التنازلية إلى كود العميل (الكود الذي يشير إلى الأنواع العامة). بالمقارنة مع الكود غير العام الذي يستخدم التحويلات اليدوية، ستكون هذه التحويلات متطابقة، [ 73 ] ولكن بالمقارنة مع الكود الذي يتم التحقق منه أثناء الترجمة والذي لا يحتاج إلى تحويلات وفحوصات أثناء التشغيل، فإن هذه العمليات تمثل عبئًا إضافيًا على الأداء.تضمن الأنواع العامة في لغة C#/.NET سلامة الأنواع ويتم التحقق منها أثناء الترجمة، مما يجعل عمليات التحقق/التحويل الإضافية غير ضرورية أثناء التشغيل. وبالتالي، سيعمل الكود العام بشكل أسرع من الكود غير العام (أو الذي تم حذف نوعه) والذي يتطلب تحويلات عند التعامل مع الكائنات غير العامة أو التي تم حذف نوعها.
لا يمكن استخدام الأنواع الأولية كمعاملات للأنواع؛ بدلاً من ذلك، يجب على المطور استخدام نوع الغلاف المطابق للنوع الأولي. يؤدي هذا إلى زيادة في الحمل على الأداء نتيجةً لمتطلبات تحويلات التغليف وفك التغليف، بالإضافة إلى زيادة الضغط على الذاكرة وجمع البيانات المهملة، حيث سيتم تخصيص الأغلفة في الكومة بدلاً من المكدس.يُسمح باستخدام أنواع البيانات الأولية وأنواع القيم كمعاملات نوعية في التطبيقات العامة. عند التشغيل، يتم توليد وتجميع الكود لكل تركيبة فريدة من معاملات النوع عند الاستخدام الأول. لا تتطلب التطبيقات العامة المُنفذة باستخدام أنواع البيانات الأولية/القيمية عمليات تحويل التغليف/فك التغليف.
الاستثناءات العامة غير مسموح بها [ 74 ] ولا يمكن استخدام معلمة النوع في عبارة catch [ 75 ]يمكن تعريف الاستثناءات العامة واستخدامها في عبارات catch.
يتم مشاركة الأعضاء الثابتة عبر جميع التحقيقات العامة [ 76 ] (أثناء مسح النوع، يتم دمج جميع التحقيقات في فئة واحدة)تكون الأعضاء الثابتة منفصلة لكل تطبيق عام. التطبيق العام هو فئة فريدة.
لا يمكن استخدام معلمات النوع في تعريفات الحقول/الأساليب الثابتة أو في تعريفات الفئات الداخلية الثابتةلا توجد قيود على استخدام معلمات النوع
لا يمكن إنشاء مصفوفة يكون فيها نوع المكون عبارة عن تحقيق عام (نوع معلمات محدد)
Pair < String , String >[] tenPairs = new Pair [ 10 ] ; // صحيح
يُعتبر التنفيذ العام عنصرًا أساسيًا ويمكن استخدامه كأي فئة أخرى؛ وهو أيضًا عنصر من عناصر المصفوفة.
object tenPairs = new Pair < int , string > [ 10 ]; // صحيح
لا يمكن إنشاء مصفوفة حيث يكون نوع المكون عبارة عن معلمة نوع، ولكن من الصحيح إنشاء Objectمصفوفة وإجراء تحويل نوع على المصفوفة الجديدة لتحقيق نفس التأثير.
class Lookup < K , V > { V [] getEmptyValues ( K key ) { return ( V [] ) new Object [ 0 ] ; // OK } }

عندما يكون مُعامل نوع عام خاضعًا لقيود التوريث، يمكن استخدام نوع القيد بدلاً منObject

class Lookup < K , V extends Comparable <V> > { V [ ] getEmptyValues ( K key ) { return ( V [] ) new Comparable [ 0 ] ; } }
تمثل معلمات النوع فئات منفصلة فعلية ويمكن استخدامها مثل أي نوع آخر ضمن التعريف العام.
public class Lookup < K , V > { public V [] GetEmptyValues ( K key ) { return new V [ 0 ]; // OK } }
لا يوجد تعريف حرفي للفئة يمثل تجسيدًا ملموسًا لنوع عامإن التحقيق العام هو فئة فعلية.
لا يُسمح باستخدام instanceof مع معلمات النوع أو التطبيقات العامة الملموسةتعمل المعاملات is و as بنفس الطريقة بالنسبة لمعاملات النوع كما هو الحال بالنسبة لأي نوع آخر .
لا يمكن إنشاء مثيلات جديدة باستخدام مُعامل نوع كنوعمع وجود قيد على المُنشئ، يمكن للأساليب العامة أو أساليب الفئات العامة إنشاء مثيلات للفئات التي تحتوي على مُنشئات افتراضية.
تُحذف معلومات النوع أثناء عملية الترجمة. يجب استخدام امتدادات خاصة للانعكاس لاكتشاف النوع الأصلي.يتم الحفاظ على معلومات النوع المتعلقة بالأنواع العامة في لغة C# بشكل كامل في وقت التشغيل، مما يسمح بدعم كامل للانعكاس وإنشاء الأنواع العامة.
لا يمكن استخدام الانعكاس لإنشاء تطبيقات عامة جديدة. أثناء عملية الترجمة، يتم إدخال شيفرة إضافية (تحويلات الأنواع) في شيفرة العميل للتطبيقات العامة. هذا يمنع إنشاء تطبيقات جديدة لاحقًا.يمكن استخدام الانعكاس لإنشاء تطبيقات جديدة لمجموعات جديدة من معلمات النوع.

تسمح لغة C# باستخدام الأنواع العامة مباشرةً مع الأنواع الأولية. أما لغة Java، فتسمح باستخدام الأنواع المُغلّفة كمعاملات للأنواع (مثلًا، بدلًا من `<type> `). يأتي هذا بتكلفة، إذ يجب تغليف/فك تغليف جميع هذه القيم عند استخدامها، كما يجب تخصيصها في الذاكرة الديناميكية. مع ذلك، يمكن تخصيص نوع عام باستخدام نوع مصفوفة من نوع أولي في Java، على سبيل المثال، يُسمح باستخدام `<type>`. [ 77 ] قامت العديد من مكتبات الطرف الثالث بتنفيذ المجموعات الأساسية في Java باستخدام مصفوفات أولية داعمة للحفاظ على تحسين وقت التشغيل والذاكرة الذي توفره الأنواع الأولية. [ 78 ]List<Integer>List<int>List<int[]>

توافق الترحيل

استُلهم تصميم حذف الأنواع في جافا من متطلبات التصميم لتحقيق التوافق مع عمليات الترحيل ، مع التنويه إلى عدم الخلط بينه وبين التوافق مع الإصدارات السابقة . وبالتحديد، كان الشرط الأصلي هو: " ... يجب أن يكون هناك مسار ترحيل واضح وقابل للإثبات لواجهات برمجة تطبيقات المجموعات التي تم تقديمها في منصة جافا 2 ". [ 44 ] وقد صُمم هذا بحيث يمكن تمرير أي مجموعات عامة جديدة إلى الطرق التي تتوقع إحدى فئات المجموعات الموجودة مسبقًا. [ 79 ]

تم إدخال ميزة الأنواع العامة في لغة C# مع الحفاظ على التوافق التام مع الإصدارات السابقة، ولكن لم يتم الحفاظ على التوافق التام مع التحديثات اللاحقة : يعمل الكود القديم (قبل C# 2.0) دون تغيير على بيئة التشغيل الجديدة المتوافقة مع الأنواع العامة دون الحاجة إلى إعادة تجميع. أما بالنسبة للتوافق مع التحديثات اللاحقة ، فقد تم تطوير فئات وواجهات جديدة للمجموعات العامة تُكمّل مجموعات .NET 1.x غير العامة بدلاً من استبدالها. بالإضافة إلى واجهات المجموعات العامة، تُطبّق فئات المجموعات العامة الجديدة واجهات المجموعات غير العامة حيثما أمكن. هذا يمنع استخدام المجموعات العامة الجديدة مع الطرق الموجودة مسبقًا (غير المتوافقة مع الأنواع العامة)، إذا كانت هذه الطرق مُبرمجة لاستخدام فئات المجموعات .

التغاير والتغاير العكسي

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

البرمجة الوظيفية

البرمجة الوظيفيةجافاسي شارب
مراجع المنهجنعم [ 80 ]نعم
عمليات الإغلاقلا تُضيف جميع تعابير لامدا مستوى جديدًا من النطاق. يجب أن تكون جميع المتغيرات المُشار إليها نهائية فعليًا.نعم
تعبيرات لامدانعم [ 81 ]نعم
أشجار التعبيرلانعم
لغة الاستعلام العامة / واجهة برمجة التطبيقاتنعم؛ واجهة برمجة تطبيقات Java Stream (Monad) [ 82 ]نعم
تحسينات مُترجم التكرار الذيللا [ 83 ]متوفر فقط على x64 [ 84 ]

عمليات الإغلاق

الإغلاق هو دالة مضمنة تلتقط المتغيرات من نطاقها المعجمي.

تدعم لغة C# الدوال المغلقة كطرق مجهولة أو تعبيرات لامدا مع دلالات إغلاق كاملة الميزات . [ 85 ] [ 86 ]

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

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

لامدا وأشجار التعبير

تتميز لغتا C# و Java بنوع خاص من الدوال المغلقة المضمنة تُسمى دوال لامدا . هذه الدوال مجهولة الهوية: لها توقيع وجسم، ولكن ليس لها اسم. تُستخدم بشكل أساسي لتحديد وسائط محلية ذات قيم دوال في استدعاءات دوال أخرى، وهي تقنية ترتبط بشكل رئيسي بالبرمجة الوظيفية .

تتيح لغة C#، على عكس لغة Java، استخدام دوال لامدا لتعريف هياكل بيانات خاصة تُسمى أشجار التعبير. ويعتمد تصنيفها كدالة قابلة للتنفيذ أو كهيكل بيانات على استنتاج نوع المُصرّف ونوع المتغير أو المعامل الذي تُسند إليه أو تُحوّل إليه. وتلعب دوال لامدا وأشجار التعبير أدوارًا محورية في استعلام اللغة المتكامل (LINQ).

البيانات الوصفية

البيانات الوصفيةجافاسي شارب
بيانات التعريف/السماتيعتمد على الواجهة؛ يمكن إنشاء التعليقات التوضيحية التي يحددها المستخدم [ 87 ]التصنيف الطبقي
الحجج الموضعيةلا؛ إلا إذا كان هناك سبب واحد.نعم
الوسائط المسماةنعمنعم
القيم الافتراضيةحسب التعريفمن خلال التهيئة
الأنواع المتداخلةنعمنعم
التخصصلانعم
البيانات الوصفية المشروطةلانعم

المعالجة المسبقة والتجميع والتغليف

المعالجة المسبقة والتجميع والتغليفجافاسي شارب
مساحات الأسماءالطرودمساحات الأسماء
محتويات الملفحرحر
التغليفطَردإمكانية الوصول العام/الداخلي إلى أعضاء مساحة الاسم، والتي يترجمها نظام البناء إلى وحدات وتجميعات على مستوى CLR
مسار البحث عن الفئات/التجميعمسار الفئة ومسار الوحدةوقت الترجمة ووقت التشغيل [ 88 ] [ 89 ]
التجميع المشروطلا؛ تعالج لغة جافا هذا الأمر في طبقات أخرى، مثل أدوات البناء وآليات وقت التشغيل.نعم
أخطاء/تحذيرات مخصصةنعم؛ معالج التعليقات التوضيحيةنعم
مناطق صريحةلانعم

مساحات الأسماء ومحتويات الملفات

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

تسمح كلتا اللغتين باستيراد الأصناف (كما في جافا مثلاً)، مما يتيح الإشارة إلى الصنف باستخدام اسمه فقط. أحيانًا، توجد أصناف تحمل الاسم نفسه في مساحات أسماء أو حزم متعددة. يمكن الإشارة إلى هذه الأصناف باستخدام الأسماء الكاملة، أو باستيراد أصناف محددة بأسماء مختلفة. وللقيام بذلك، تسمح جافا باستيراد صنف واحد (مثلاً، ). أما لغة C# فتسمح باستيراد الأصناف تحت اسم محلي جديد باستخدام الصيغة التالية: . كما تسمح باستيراد تخصصات الأصناف على شكل .importjava.util.*importjava.util.ListusingConsole=System.ConsoleusingIntList=System.Collections.Generic.List<int>

تتميز كلتا اللغتين بصيغة استيراد ثابتة تسمح باستخدام الاسم المختصر لبعض أو كل الدوال/الحقول الثابتة في فئة ما (على سبيل المثال، السماح باستيراد foo(bar)دالة foo()ثابتة من فئة أخرى). تعتمد لغة C# على صيغة فئات ثابتة (لا ينبغي الخلط بينها وبين الفئات الداخلية الثابتة في Java)، مما يقصر محتوى الفئة على الدوال الثابتة فقط. يُقدم الإصدار 3.0 من C# دوال الإضافة التي تسمح للمستخدمين بإضافة دالة ثابتة إلى نوع ما (على سبيل المثال، السماح foo.bar()باستيراد bar()دالة إضافة تعمل على نوع foo ).

يشترط مُصرّف جافا من صن مايكروسيستمز أن يتطابق اسم ملف المصدر مع اسم الفئة العامة الوحيدة الموجودة فيه، بينما يسمح C# بوجود فئات عامة متعددة في الملف نفسه، ولا يفرض أي قيود على اسم الملف. يسمح C# 2.0 والإصدارات الأحدث بتقسيم تعريف الفئة إلى عدة ملفات باستخدام الكلمة المفتاحية partial في شفرة المصدر. في جافا، تكون الفئة العامة دائمًا في ملف مصدر خاص بها. أما في C#، فلا توجد علاقة وثيقة بين ملفات شفرة المصدر وفصل الوحدات المنطقية.

التجميع المشروط

على عكس جافا، تُنفّذ لغة C# الترجمة الشرطية باستخدام توجيهات المعالج المسبق . كما توفر سمة Conditional لتعريف الدوال التي تُستدعى فقط عند تعريف ثابت ترجمة مُحدد. بهذه الطريقة، يُمكن توفير التأكيدات كميزة إطار عمل باستخدام الدالة التي تُقيّم فقط عند تعريف ثابت DEBUG . منذ الإصدار 1.4، توفر جافا ميزة لغوية للتأكيدات، وهي مُعطّلة افتراضيًا أثناء التشغيل، ولكن يُمكن تفعيلها باستخدام مفتاح التبديل عند استدعاء JVM.Debug.Assert()-enableassertions-ea

ميزات الترابط والتزامن

تتضمن كلتا اللغتين آليات مزامنة الخيوط كجزء من بناء الجملة اللغوية.

الربط والتزامنجافاسي شارب
الخيوطنعمنعم
مجموعة الخيوطنعمنعم
التوازي القائم على المهامنعم [ 90 ]نعم [ 91 ]
إشارات المرورنعمنعم
الشاشاتنعمنعم
المتغيرات المحلية للخيطنعمنعم ؛ ThreadStaticAttribute والفئةThreadLocal<T>

التوازي القائم على المهام للغة C#

مع إصدار .NET Framework 4.0، تم تقديم نموذج برمجة جديد قائم على المهام ليحل محل النموذج غير المتزامن القائم على الأحداث. تعتمد واجهة برمجة التطبيقات (API) على المهام والفئات . ويمكن دمج المهام وربطها ببعضها البعض.Task<T>

بحسب العرف، يجب أن يكون اسم كل طريقة تُرجع مهمة (Task) متبوعًا بـ Async .

باستخدام System.Threading.Tasks ؛public static class SomeAsyncCode { public static Task <XDocument> GetContentAsync ( ) { HttpClient httpClient = new ( ); return httpClient.GetStringAsync ( " www.contoso.com" ) . ContinueWith (( task ) = > { string responseBodyAsText = task.Result ; return XDocument.Parse ( responseBodyAsText ) ; } ) ; } }Task t = SomeAsyncCode.GetContentAsync ( ) . ContinueWith ( ( task ) => { XDocument xmlDocument = task.Result ; } ) ;t . ابدأ ();

في لغة C# 5، تم تقديم مجموعة من امتدادات اللغة والمترجم لتسهيل التعامل مع نموذج المهام. تضمنت هذه الامتدادات مفهوم الأساليب غير المتزامنة وعبارة await التي تجعل تدفق البرنامج يبدو متزامنًا.

باستخدام System.Threading.Tasks ؛public static class SomeAsyncCode { public static async Task <XDocument> GetContentAsync ( ) { HttpClient httpClient = new ( ) ; string responseBodyAsText = await httpClient.GetStringAsync ( " www.contoso.com" ) ; return XDocument.Parse ( responseBodyAsText ) ; } }XDocument xmlDocument = await SomeAsyncCode . GetContentAsync ();// سيتم بدء المهمة عند استدعائها باستخدام await.

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

التوازي القائم على المهام للغة جافا

يدعم جافا الخيوط منذ إصدار JDK 1.0. يوفر جافا مرونة عالية لتشغيل الخيوط، والتي تُسمى غالبًا بالمهام. يتم ذلك من خلال تطبيق واجهة وظيفية ( java.lang.Runnableواجهة) تُعرّف دالة واحدة من نوع void بدون وسائط، كما هو موضح في المثال التالي:

var myThread = new Thread (() -> {String threadName = Thread.currentThread (). getName ( ) ;System.out.println ( " Hello " + threadName ) ;});myThread.start ( ) ;

على غرار لغة C#، تمتلك Java آلية عالية المستوى للتعامل مع الخيوط. يمكن للمنفذين تنفيذ المهام غير المتزامنة وإدارة مجموعة من العمليات الفرعية. تُدار جميع خيوط مثيل ExecutorService في مجمع . يُعاد استخدام مثيل ExecutorService هذا داخليًا للمهام المتكررة، مما يُتيح للمبرمج تشغيل أي عدد من المهام المتزامنة طوال دورة حياة التطبيق باستخدام مثيل ExecutorService واحد. علاوة على ذلك، تدعم Java الخيوط الافتراضية ، وهي خيوط خفيفة الوزن للغاية تسمح بتزامن هائل دون أي تكلفة إضافية للخيوط التقليدية في النظام الأساسي، على الرغم من استخدامها جنبًا إلى جنب مع نموذج ExecutorService القياسي.

هكذا يبدو المثال الأول للخيط باستخدام المنفذين:

استيراد الوحدة النمطية java.base ؛var executor = Executors . newSingleThreadExecutor ();executor.submit ( () - > {var threadName = Thread.currentThread (). getName ( ) ;IO.println ( "Hello " + threadName ) ;});

يدعم مثيل ExecutorService أيضًا واجهة Callable ، وهي واجهة أخرى ذات دالة واحدة مثل Runnable، ولكن توقيع الدالة المُضمنة في Callable يُرجع قيمة. وبهذه الطريقة، يجب أن يُرجع تعبير lambda قيمة أيضًا، كما في المثال أدناه لاستدعاء موقع ويب بشكل غير متزامن في مثال C#.

استيراد الوحدة النمطية java.base ؛استيراد وحدة جافا.نت. http ؛class SomeAsyncCode {static Future <String> getContentAsync ( ) {var executor = Executors . newSingleThreadExecutor ();return executor.submit ( () - > {var httpReq = HttpRequest.newBuilder ( ). uri ( new URI ( "https://www.graalvm.org" )). يبني ()؛return HttpClient.newHttpClient ( ). إرسال ( httpReq , HttpResponse . BodyHandlers . ofString ()). جسم ()؛});}}void main () throws Exception {var webPageResult = SomeAsyncCode . الحصول على المحتوى (). يحصل ()؛IO.println ( webPageResult ) ;}

يؤدي استدعاء هذه الطريقة get()إلى حظر الخيط الحالي والانتظار حتى يكتمل استدعاء الدالة قبل إرجاع القيمة (في المثال، محتوى صفحة ويب):

ميزات إضافية

التطبيقات العددية

ولتوفير الدعم الكافي للتطبيقات في مجال الحسابات الرياضية والمالية، توجد العديد من ميزات اللغة. [ 92 ]

تُمكّن الكلمة المفتاحية strictfp في لغة جافا من إجراء حسابات دقيقة للأعداد العشرية في جزء من الكود. تتطلب هذه الحسابات تحويل النتائج الوسيطة إلى نوعي Single/Double، حتى لو كانت المنصة تدعم دقة أعلى أثناء الحساب. يضمن هذا أن تُعيد حسابات الأعداد العشرية الدقيقة نفس النتيجة تمامًا على جميع المنصات. بدون استخدام الأعداد العشرية الدقيقة، يُمكن للمنصة استخدام دقة أعلى للنتائج الوسيطة أثناء الحساب. تسمح لغة C# للتنفيذ، المُصمم لبنية أجهزة معينة، باستخدام دقة أعلى للنتائج الوسيطة دائمًا، إن توفرت، أي أن C# لا تسمح للمبرمج بفرض استخدام دقة أقل للنتائج الوسيطة. [ 93 ]

على الرغم من أن حسابات الفاصلة العائمة في جافا تعتمد إلى حد كبير على معيار IEEE 754 (معيار حسابات الفاصلة العائمة الثنائية)، إلا أن بعض الميزات غير مدعومة حتى عند استخدام مُعدِّل strictfp، مثل علامات الاستثناء والتقريب الموجه، وهي قدرات يفرضها معيار IEEE 754 (انظر نقد جافا، حسابات الفاصلة العائمة ).

توفر لغة C# نوع بيانات عشري مدمجًا، [ 94 ] يتميز بدقة أعلى (ولكن بنطاق أضيق) من نوع البيانات double في Java/C#. يُعدّ النوع العشري نوع بيانات 128 بت، وهو مناسب للحسابات المالية والنقدية. يمكن لهذا النوع تمثيل قيم تتراوح من 1.0 × 10⁻²⁸ إلى حوالي 7.9 × 10²⁸ ، مع 28-29 رقمًا معنويًا. [ 95 ] يستخدم هذا النوع خاصية تحميل المعاملات الزائدة في C#، مما يسمح بمعالجة الأعداد العشرية باستخدام معاملات مثل + و- و * و / ، تمامًا مثل أنواع البيانات الأولية الأخرى.

تتيح أنواع البيانات BigDecimal`int` و`int` BigIntegerالمتوفرة في جافا تمثيل الأعداد العشرية والأعداد الصحيحة بدقة غير محدودة، على التوالي. ولا تحتوي مكتبة جافا القياسية على فئات للتعامل مع الأعداد المركبة.

تتيح الأنواع BigInteger[ 3 ] و [ 96 ] المتوفرة في لغة C# تمثيل ومعالجة الأعداد الصحيحة والأعداد المركبة ذات الدقة العشوائية، على التوالي. تستخدم هذه البنى خاصية تحميل المعاملات الزائدة في C#، مما يسمح بمعالجة الكائنات باستخدام معاملات مثل + و- و * و / ، كما هو الحال مع أنواع البيانات الأولية الأخرى. لا تحتوي مكتبة C# القياسية على فئات للتعامل مع أعداد الفاصلة العائمة ذات الدقة العشوائية (انظر برنامج العمليات الحسابية ذات الدقة العشوائية ).Complex

يمكن للغة C# أن تساعد التطبيقات الرياضية باستخدام checkedعوامل uncheckedالتشغيل التي تسمح بتمكين أو تعطيل التحقق من تجاوز السعة الحسابية في وقت التشغيل لمنطقة معينة من التعليمات البرمجية.

الاستعلام المتكامل مع اللغة (LINQ)

تُعد ميزة الاستعلام المتكامل للغة C# (LINQ) مجموعة من الميزات المصممة للعمل معًا للسماح بإمكانيات الاستعلام داخل اللغة، وهي ميزة مميزة بين C# و Java.

يتضمن LINC هذه الميزات:

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

قابلية التشغيل البيني الأصلية

ميزة التشغيل البيني الأصليةجافاسي شارب
قابلية التشغيل البيني عبر اللغاتنعم (FFM API [ 97 ] ، JNI ، JNA )نعم؛ لقد صُممت لغة C# لهذا الغرض.

[ 98 ]

الطرق الخارجية / الأصليةنعم [ 99 ]

[ 100 ]

نعم (P/Invoke) [ 101 ]
التنسيقنعم (تخطيطات الذاكرة الصريحة) [ 102 ]نعم؛ يتم التحكم في البيانات الوصفية [ 103 ]
المؤشرات والحسابنعم (مقيد، عبر MemorySegment) [ 104 ]نعم [ 105 ]
تخصيص الذاكرة الأصلينعم (Arena, allocateNative) [ 106 ]نعم [ 107 ]
تخصيص المكدس الصريحلا (ولكن بدلاً من ذلك، فإنه يستخدم تخصيص الذاكرة القائم على الساحة، مما يوفر نموذجًا أبسط وأكثر تنظيمًا لعمر الذاكرة) [ 108 ]نعم (`stackalloc`) [ 109 ]
عنوان المشغللا (لا توفر واجهة برمجة تطبيقات FFM عامل عنوان؛ بدلاً من ذلك، فهي تمثل الذاكرة الأصلية من خلال مقاطع الذاكرة ذات فترات حياة مُدارة، مما يفرض وصولاً أكثر أمانًا وقابلية للتنبؤ إلى الذاكرة.) [ 110 ]نعم [ 111 ]
تثبيت الكائناتنعم (ذاكرة خارج الكومة غير متحركة) [ 112 ]نعم [ 113 ]
مؤشرات الدوالنعم (مكالمات تصاعدية) [ 114 ]نعم [ 115 ]
النقاباتنعم (تخطيطات متداخلة) [ 116 ]نعم [ 117 ]

توفر منصة جافا آليات متعددة للتفاعل مع التعليمات البرمجية الأصلية. أحدث هذه الآليات هي واجهة برمجة تطبيقات الوظائف الخارجية والذاكرة (FFM API)، التي طُوّرت ضمن مشروع بنما [ 118 ] ، والتي تُقدّم منهجًا معياريًا أكثر أمانًا وكفاءة لاستدعاء الوظائف الأصلية والوصول إلى الذاكرة الأصلية دون الاعتماد على واجهة جافا الأصلية (JNI). تُقلّل واجهة FFM API من الحمل الزائد وتُزيل الكثير من التعليمات البرمجية المتكررة المرتبطة تقليديًا بـ JNI، مع تمكين أداء أقرب إلى الأداء الأصلي والحفاظ على ضمانات السلامة ودورة حياة التعليمات البرمجية. [ 119 ]

تاريخياً، كانت JNI هي الآلية الأساسية للتوافق الأصلي في Java ولا تزال تستخدم على نطاق واسع في قواعد التعليمات البرمجية الحالية.

تتيح ميزة واجهة جافا الأصلية (JNI) لبرامج جافا استدعاء أكواد غير مكتوبة بلغة جافا. مع ذلك، تتطلب JNI من الكود المُستدعى اتباع عدة اصطلاحات، وتفرض قيودًا على أنواع البيانات والأسماء المستخدمة. هذا يعني الحاجة غالبًا إلى طبقة وسيطة إضافية بين الكود القديم وجافا. يجب كتابة هذا الكود الوسيط بلغة غير جافا، غالبًا C أو C++. أما ميزة الوصول الأصلي لجافا (JNA) فتتيح استدعاءً أسهل للأكواد الأصلية، ما يتطلب كتابة كود جافا فقط، ولكن على حساب الأداء.

بالإضافة إلى ذلك، توفر مكتبات الطرف الثالث جسر نموذج كائن المكون (COM)، على سبيل المثال، JACOB ( برنامج مجاني ) و J-Integra لـ COM ( برنامج احتكاري ).

عادةً ما يوجد الكود الأصلي في مكتبة ، والتي يمكن لجافا التفاعل معها عبر هذه الآليات.

توفر منصة .NET للاستدعاء ( P/Invoke ) نفس الإمكانية من خلال السماح باستدعاءات من لغة C# لما تسميه مايكروسوفت " التعليمات البرمجية غير المُدارة" . يستطيع المبرمج، عبر سمات البيانات الوصفية، التحكم بدقة في كيفية معالجة المعاملات والنتائج ، متجنبًا بذلك الحاجة إلى التعليمات البرمجية الخارجية اللازمة لـ JNI المكافئ في Java. تتيح P/Invoke وصولًا شبه كامل إلى واجهات برمجة التطبيقات الإجرائية (مثل Win32 أو POSIX)، ولكن وصولًا محدودًا إلى مكتبات فئات C++.

بالإضافة إلى ذلك، يوفر إطار عمل .NET أيضًا جسر .NET-COM، مما يسمح بالوصول إلى مكونات COM كما لو كانت كائنات .NET من الدرجة الأولى.

تتيح لغة C# للمبرمج تعطيل التحقق من الأنواع وميزات الأمان الأخرى في بيئة CLR ، مما يسمح باستخدام متغيرات المؤشر . عند استخدام هذه الميزة، يجب على المبرمج وضع علامة على الكود باستخدام الكلمة المفتاحية `unsafe` . تُعدّ كل من JNI وP/Invoke والكود "غير الآمن" ميزات خطيرة بنفس القدر، إذ تُعرّض التطبيقات لثغرات أمنية محتملة وعدم استقرار. من مزايا الكود المُدار غير الآمن مقارنةً بـ P/Invoke أو JNI أنه يسمح للمبرمج بمواصلة العمل في بيئة C# المألوفة لإنجاز بعض المهام التي تتطلب عادةً استدعاء كود غير مُدار. يجب تجميع أي برنامج أو مكتبة تستخدم كودًا غير آمن باستخدام مفتاح خاص، وسيتم وضع علامة عليه. يُمكّن هذا بيئات التشغيل من اتخاذ احتياطات خاصة قبل تنفيذ أي كود قد يكون ضارًا.

بيئات وقت التشغيل

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

صُممت لغة C# للتنفيذ على بيئة تشغيل اللغة المشتركة (CLR). صُممت بيئة تشغيل اللغة المشتركة لتنفيذ التعليمات البرمجية المُترجمة بالكامل. يُنتج مُترجم لغة C# تعليمات لغة وسيطة مشتركة . عند التنفيذ، تقوم بيئة التشغيل بتحميل هذه التعليمات البرمجية وترجمتها إلى تعليمات الآلة على بنية النظام المستهدف.

أمثلة

المدخلات/المخرجات

مثال يوضح كيفية نسخ النص سطرًا سطرًا من ملف إلى آخر، باستخدام اللغتين.

جافاسي شارب
استيراد الوحدة النمطية java.base ؛void main () throws Exception { var input = Paths . get ( "input.txt" ); var output = Paths . get ( "output.txt" );var lines = Files.readAllLines ( input ) ; Files.write ( output , lines ) ; }
باستخدام System.Collections.Generic ؛ باستخدام System.IO ؛class FileIOTest { public static void Main ( string [] args ) { IEnumerable < string > lines = File . ReadLines ( "input.txt" ); File . WriteAllLines ( "output.txt" , lines ); } }
ملاحظات حول تطبيق جافا:
  • Files.readAllLinesتقوم الدالة بإرجاع قائمة من السلاسل النصية، تحتوي على محتوى ملف النص، كما تحتوي الدالة Files أيضًا على الدالة readAllBytes ، التي تُرجع مصفوفة من السلاسل النصية .
  • Files.writeتقوم هذه الطريقة بكتابة مصفوفة بايت أو في ملف إخراج، يتم تحديده بواسطة كائن المسار.
  • Files.writeتتولى هذه الطريقة أيضًا مهمة التخزين المؤقت وإغلاق دفق الإخراج.
ملاحظات حول تطبيق لغة C#:
  • تقوم طريقة ReadLines بإرجاع كائن قابل للتعداد يقوم عند التعداد بقراءة الملف سطرًا واحدًا في كل مرة.
  • تأخذ طريقة WriteAllLines مجموعة قابلة للتعداد وتسترجع سطرًا واحدًا في كل مرة وتكتبه حتى ينتهي التعداد.
  • سيقوم القارئ الأساسي بتخصيص مخزن مؤقت تلقائيًا، وبالتالي لا حاجة لإدخال دفق مخزن مؤقت بشكل صريح.
  • تقوم وظيفة WriteAllLines بإغلاق دفق الإخراج تلقائيًا، حتى في حالة الإنهاء غير الطبيعي.

دمج الأنواع المعرفة بواسطة المكتبة

تتيح لغة C# دمج الأنواع المعرفة في المكتبة مع الأنواع والمعاملات الموجودة باستخدام التحويلات الضمنية/الصريحة المخصصة وتحميل المعاملات الزائد كما هو موضح في المثال التالي:

جافاسي شارب
استيراد java.math.BigInteger ؛BigInteger bigNumber = BigInteger ( "123456789012345678901234567890" );BigInteger answer = bigNumber.multiply ( BigInteger.valueOf ( 42 ) ) ; BigInteger square = bigNumber.sqrt ( ) ; BigInteger sum = bigNumber.add ( bigNumber ) ;
باستخدام System.Numerics ؛BigInteger bigNumber = BigInteger.Parse ( "123456789012345678901234567890 " ) ;عدد صحيح كبير للإجابة = العدد الكبير * 42 ؛ عدد صحيح كبير للمربع = العدد الكبير * العدد الكبير ؛ عدد صحيح كبير للمجموع = العدد الكبير + العدد الكبير ؛

المندوبون في لغة C# وما يعادلهم من بنيات في لغة Java

جافاسي شارب
استيراد java.util.Function ;// فئة الهدف class Target { public boolean targetMethod ( String arg ) { // قم بتنفيذ شيء ما return true ; } }// طريقة الاستخدام void doSomething () { // إنشاء كائن هدف باستخدام دالة الهدف Target target = new Target ();// التقاط مرجع الدالة Function < String , Boolean > ivk = target :: targetMethod ;// يستدعي الدالة المشار إليها bool result = ivk.apply ( "argumentstring" ) ; }
باستخدام النظام ؛// فئة الهدف class Target { public bool TargetMethod ( string arg ) { // قم بتنفيذ شيء ما return true ; } }// طريقة الاستخدام void DoSomething () { // إنشاء هدف باستخدام دالة الهدف Target target = new ();// التقاط المندوب لاستدعائه لاحقًا Func < string , bool > dlg = target . TargetMethod ;// استدعاء الدالة المفوضة bool result = dlg ( "argumentstring" ); }

نوع الرفع

جافاسي شارب

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

استيراد java.util.Optional ;Optional <Integer> a = Optional.of ( 42 ) ; Optional <Integer> b = Optional . <Integer> empty ( ) ;Optional <Integer> c = a.flatMap ( aa- > b.map ( bb- > aa * bb ) ) ;
int? a = 42 ; int? b = null ;// ستتلقى c القيمة الفارغة // لأن * يتم رفعها وأحد المعاملات فارغ int? c = a * b ;

التوافق مع اللغات الديناميكية

يوضح هذا المثال كيفية استخدام لغتي Java وC# لإنشاء واستدعاء نسخة من فئة مُنفذة بلغة برمجة أخرى. فئة "Deepthought" مُنفذة بلغة برمجة Ruby ، وهي عبارة عن آلة حاسبة بسيطة تقوم بضرب قيمتين مُدخلتين ( a و b ) عند استدعاء دالة Calculate . بالإضافة إلى الطريقة التقليدية، توفر Java آلة GraalVM الافتراضية، القادرة على تشغيل أي لغة برمجة مُنفذة.

جافاسي شارب

استخدام GraalVM

Context polyglot = Context.newBuilder (). allowAllAccess ( true ) .build ( ) ;// Ruby Value rubyArray = polyglot.eval ( "ruby" , " [ 1,2,42,4]" ); int rubyResult = rubyArray.getArrayElement ( 2 ) .asInt ( ) ;// قيمة بايثون pythonArray = polyglot.eval ( " python " , " [ 1,2,42,4]" ) ; int pythonResult = pythonArray.getArrayElement ( 2 ) .asInt ( );// قيمة جافا سكريبت jsArray = متعدد اللغات . إيفال ( "js" ، "[1,2,42,4]" int jsResult = jsArray . الحصول على عنصر الصفيف ( 2 ). asInt ();// قيمة R rArray = polyglot.eval ( "R" , " c ( 1,2,42,4)" ); int rResult = rArray.getArrayElement ( 2 ) .asInt ( );// LLVM (في هذه الحالة C، ولكن يمكن أن تكون C++ أو Go أو Basic، إلخ...) المصدر source = Source.newBuilder ( " llvm " , new File ( "C_Program.bc" )). build (); القيمة cpart = polyglot.eval ( source ) ; cpart.getMember ( " main " ). execute ( );

الطريقة التقليدية

استيراد java.io.FileReader ؛ استيراد javax.script.* ؛ استيراد org.jruby.* ؛// تهيئة المحرك ScriptEngineManager invocable = new ScriptEngineManager ( ). getEngineByName ( "jruby" ); FileReader rubyFile = new FileReader ( "Deepthought.rb" ); engine.eval ( fr ) ;
// إنشاء نسخة جديدة من آلة حاسبة "Deepthought" Object calcClass = engine.eval ( " Deepthought " ); Object calc = invocable.invokeMethod ( calcClass , " new" );// ضبط قيم إدخال الآلة الحاسبة invocable.invokeMethod ( calc , " a=" , 6 ) ; invocable.invokeMethod ( calc , "b=" , 7 ) ;// حساب النتيجة Object answer = invocable.invokeMethod ( calc , "Calculate" ) ;
باستخدام System ؛ باستخدام Microsoft.Scripting.Hosting ؛ باستخدام IronRuby ؛// تهيئة المحركScriptRuntime runtime = ScriptRuntime.CreateFromConfiguration ( ) ; dynamic globals = runtime.Globals ;runtime.ExecuteFile ( "Deepthought.rb " ) ;
// إنشاء نسخة جديدة من آلة حاسبة "Deepthought" ديناميكيًا calc = globals.Deepthought . @ new ( );// ضبط قيم إدخال الآلة الحاسبة calc.a = 6 ; calc.b = 7 ;// حساب النتيجة ديناميكيًا الإجابة = calc.Calculate ( );

ملاحظات حول تطبيق جافا:

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

ملاحظات حول تطبيق لغة C#:

  • تكون الكائنات المُعادة من خصائص أو أساليب الكائنات الديناميكية من النوع الديناميكي نفسه . عند استخدام استنتاج النوع ( الكلمة المفتاحية var )، يتم استنتاج أن المتغيرين calc و answer ديناميكيان/مرتبطان لاحقًا.
  • الكائنات الديناميكية ذات الحدود المتأخرة هي كائنات من الدرجة الأولى يمكن التلاعب بها باستخدام بناء جملة C# على الرغم من أنها تم إنشاؤها بواسطة لغة خارجية.
  • كلمة "جديد " كلمة محجوزة. @يسمح البادئة باستخدام الكلمات المفتاحية كمعرفات.

متتالية فيبوناتشي

يوضح هذا المثال كيفية تطبيق متتالية فيبوناتشي باستخدام اللغتين. تستفيد نسخة C# من دوال المولدات الخاصة بها ، بينما تستفيد نسخة Java من واجهة Stream ومراجع الدوال. يستخدم كلا المثالين، Java وC#، أسلوب K&R لتنسيق الكود الخاص بالفئات والدوال والعبارات.

جافاسي شارب
// سلسلة فيبوناتشي Stream.generate ( new Supplier <Integer> ( ) { int a = 0 ; int b = 1 ;public Integer get () { int temp = a ; a = b ; b = a + temp ; return temp ; } } ) . limit ( 10 ) .forEach ( System.out :: println ) ;
باستخدام System.Collections.Generic ؛// متتالية فيبوناتشي العامة IEnumerable <int> Fibonacci ( ) { int a = 0 ; int b = 1 ;بينما ( صحيح ) { أرجع a ؛ ( a ، b ) = ( b ، a + b ) ؛ } }
// اطبع أول 10 أعداد من متتالية فيبوناتشي foreach ( int it in Fibonacci (). Take ( 10 )) { Console . WriteLine ( it ); }
ملاحظات خاصة بإصدار جافا:
  • تُعد واجهة Java 8 Stream عبارة عن سلسلة من العناصر التي تدعم عمليات التجميع المتسلسلة والمتوازية.
  • تقوم طريقة الإنشاء بإرجاع سلسلة غير مرتبة لا نهائية حيث يتم إنشاء كل عنصر بواسطة المورد المقدم.
  • تقوم طريقة الحد بإرجاع دفق يتكون من عناصر هذا الدفق، مع اقتطاعه بحيث لا يتجاوز طوله maxSize.
  • تقوم طريقة forEach بتنفيذ إجراء لكل عنصر من عناصر هذا التدفق، ويمكن أن يكون هذا الإجراء عبارة عن تعبير لامدا أو مرجع طريقة.

باستخدام حلقة تكرارية (foreach)

نفس المثال السابق، ولكن باستخدام دالة تُرجع كائنًا قابلًا للتكرار للحفاظ على تشابه أكبر مع مثال C#. أي عنصر يُطبّق واجهة iterable يمكن تكراره في حلقة foreach.

استيراد java.util.stream.Stream ؛ استيراد java.util.function.Supplier ؛Iterable <Integer> fibonacci ( int limit ) { return Stream.generate ( new Supplier <Integer> ( ) { int a = 0 ; int b = 1 ; public Integer get ( ) { int temp = a ; a = b ; b = a + temp ; return temp ; } } ) . limit ( limit ) :: iterator ; }
// اطبع أول 10 أعداد من متتالية فيبوناتشي for ( int it : fibonacci ( 10 )) { System . out . println ( it ); }

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

فيما يلي مثال يستخدم التدفقات وجمع التدفقات عن طريق استدعاء toList في كتلة foreach.

استيراد java.util.stream.Stream ؛ استيراد java.util.function.Supplier ؛Stream <Integer> fibonacci = Stream.generate ( new Supplier <Integer> ( ) { int a = 0 ; int b = 1 ; public Integer get ( ) { int temp = a ; a = b ; b = a + temp ; return temp ; } } ) ;
// اطبع أول 10 أعداد من متتالية فيبوناتشي for ( int it : fibonacci . limit ( 10 ). toList ()) { System . out . println ( it ); }

بالإضافة إلى جامع البيانات toList الموجود في حلقة foreach، تجدر الإشارة إلى وجود المزيد من جامعي البيانات لكل نوع من أنواع المجموعات. كما يمكن إنشاء جامعي بيانات مخصصين بتطبيق واجهة Collector أو وصف التطبيق باستخدام تعبير لامدا، وفي كلتا الحالتين يتم تمريره كوسيط إلى دالة collect الخاصة بكائن Stream . في هذا المثال، سيتم استدعاء دالة collect بدلاً من toList إذا كان لدينا نوع معقد من الكائنات لكل عنصر في المجموعة.

يمكن أيضًا تنفيذ كلا المثالين باستخدام IntStream و IntSupplier وتجنب استخدام النوع العام Integer في تطبيق واجهة Supplier ، ولكن يتم استخدام النوع العام للحفاظ على تشابه أكبر مع مثال C#.

النمط الوظيفي

يمكن كتابة الخوارزمية المذكورة أعلاه بشكل أكثر اتساقًا باستخدام Stream.iterateدالة iterate. تستقبل هذه الدالة مُعاملًا أوليًا (seed) ودالة تُحدد الإجراء المطلوب في كل تكرار. في هذه الحالة، يمكن أن يكون المُعامل الأولي عبارة عن سجل يحتوي على القيمتين الابتدائيتين للخوارزمية، والتحويل المُناسب لكل منهما في كل تكرار. باختصار، تُغني دالة iterate عن استخدام مُورِّد (Supplier).

استيراد java.util.stream.Stream ؛سجل زوج ( عدد صحيح أ ، عدد صحيح ب ) {};Stream.iterate ( new Pair ( 0 , 1 ) , p - > new Pair ( p.b , p.a + p.b ) ) . limit ( 10 ) .map ( p - > p.a ) .forEach ( System.out :: println ) ;
ملاحظات خاصة بإصدار C#:
  • يتم تعريف الطريقة على أنها إرجاع مثيلات للواجهة ، مما يسمح لرمز العميل بطلب الرقم التالي من التسلسل بشكل متكرر.IEnumerable<int>
  • تقوم الكلمة yieldالمفتاحية بتحويل الطريقة إلى طريقة مولدة.
  • تقوم العبارة بإرجاع الرقم التالي من التسلسل وإنشاء استمرار بحيث تستمر الاستدعاءات اللاحقة لطريقة الواجهة في التنفيذ من العبارة التالية مع بقاء جميع المتغيرات المحلية سليمة.yieldreturnIEnumerableMoveNext
  • تتجنب عملية تعيين الصفوف الحاجة إلى إنشاء واستخدام متغير مؤقت عند تحديث قيم المتغيرين a و b .

انظر أيضاً

مراجع

  1. "BigDecimal (Java 2 Platform SE 5.0)" . Docs.oracle.com . تم الاطلاع عليه بتاريخ 24 فبراير 2015 .
  2. "Mpir.NET" . تم الاطلاع عليه بتاريخ 17 يوليو 2015 .
  3. 1 2 "BigInteger Struct (System.Numerics)" . learn.microsoft.com . تم الاطلاع عليه بتاريخ 14 أبريل 2023 .
  4. "مجموعة (Java 2 Platform SE 5.0)" . Docs.oracle.com . تم الاطلاع عليه بتاريخ 20 مايو 2015 .
  5. "String (Java 2 Platform SE 5.0)" . Docs.oracle.com . تم الاطلاع عليه بتاريخ 20 مايو 2015 .
  6. "الرياضيات - دليل مستخدم الرياضيات في Commons - الأعداد المركبة" . تم الاطلاع عليه بتاريخ 17 يوليو 2015 .
  7. "Date (Java 2 Platform SE 5.0)" . Docs.oracle.com . تم الاطلاع عليه بتاريخ 20 مايو 2015 .
  8. "decimal (C# Reference)" . مايكروسوفت . تم الاطلاع عليه بتاريخ 30 نوفمبر 2015 .
  9. متاح فقط في الوضع غير الآمن أو من خلالنوع مُدار بواسطة IntPtr
  10. "بنية لغة جافا" . ويكيبيديا . تاريخ الاطلاع: 7 فبراير 2026. يُعدّ java.lang.Object النوع الأعلى في جافا . إذا لم تُحدّد فئة ما نوعها الأساسي، فإنها ترث ضمنيًا من فئة java.lang.Object. وبالتالي، فإن جميع الفئات في جافا هي فئات فرعية من فئة Object.
  11. يكون نظام الأنواع موحدًا افتراضيًا، إلا إذا تم تحويل المُصرّف إلى الوضع غير الآمن حيث تتوفر المؤشرات الخام كنوع بيانات. لا تُشتق المؤشرات من الكائن، ولا توجد تحويلات ضمنية من/إلى نوع بيانات الكائن.
  12. 1 2 "فئة الصف (النظام)" . learn.microsoft.com . شركة مايكروسوفت . تم الاطلاع عليه في 20 أبريل 2023 .
  13. 1 2 "أنواع الصفوف (مرجع C#)" . learn.microsoft.com . شركة مايكروسوفت . تم الاطلاع عليه في 20 أبريل 2023 .
  14. "التعليمات البرمجية غير الآمنة، وأنواع المؤشرات، ومؤشرات الدوال" . learn.microsoft.com. 29 مايو 2022. تم الاطلاع عليه بتاريخ 14 أبريل 2023 .
  15. جوشوا بلوخ؛ نيل جافتر (2005). ألغاز جافا : الفخاخ، والمزالق، والحالات الشاذة (الطبعة الخامسة المطبوعة ). أبر سادل ريفر، نيوجيرسي [ua]: أديسون-ويسلي. ص 36. ISBN    978-0-321-33678-1الدرس المستفاد لمصممي اللغات هو أن تمديد الإشارة لقيم البايت يُعدّ مصدرًا شائعًا للأخطاء والتشويش. فالعملية اللازمة لإخفاء تمديد الإشارة تُشوّش البرامج، مما يجعلها أقل قابلية للقراءة. لذا، ينبغي أن يكون نوع البايت غير مُوقّع.{{cite book}}: صيانة CS1: أسماء متعددة: قائمة المؤلفين ( رابط )
  16. 1 2 "بيئة لغة جافا" . Oracle.com . تم الاطلاع عليه بتاريخ 18 أغسطس 2013 .
  17. "جيمس جوسلينج يتحدث عن جافا، مايو 2001" . Artima.com. 10 مايو 2001. تم الاطلاع عليه بتاريخ 24 فبراير 2015 .
  18. "Integer (Java Platform SE 8)" . Docs.oracle.com . تم الاطلاع عليه بتاريخ 20 أبريل 2023 .
  19. "decimal" . مرجع لغة C# . مايكروسوفت. 19 أغسطس 2012.
  20. 1 2 سيستوفت، جون جاغر، نايجل بيري، بيتر (2007). "11.1.7 النوع العشري". معيار C المشروح . أمستردام: دار نشر إلسيفير/مورغان كوفمان. ISBN 978-0-12-372511-0.{{cite book}}: صيانة CS1: أسماء متعددة: قائمة المؤلفين ( رابط )
  21. موك، هينغ نجي (2003). "9.5. النوع العشري". من جافا إلى سي؟: دليل المطور . هارلو، إنجلترا: أديسون ويسلي. ISBN 978-0-321-13622-0.
  22. "حزمة java.time (منصة Java SE 8)" . docs.oracle.com . تم الاطلاع عليه بتاريخ 20 أبريل 2023 .
  23. "كيفية استخدام بنيتي DateOnly و TimeOnly" . learn.microsoft.com. ١٢ يناير ٢٠٢٣. تم الاطلاع عليه بتاريخ ٢٠ أبريل ٢٠٢٣ .
  24. "Enum" . الإنترنت: .NET Perls . تاريخ الاسترجاع: 14 نوفمبر 2016. الأداء. تُعدّ أنواع التعداد سريعة. ونادرًا ما تُشكّل مصدر قلقٍ فيما يتعلق بالأداء. إنها مجرد اختصارٍ برمجي لنوع بيانات مثل int، وهو سريعٌ أيضًا. [...] النوع. لكل نوع تعداد نوعٌ أساسي. في كل مرة نستخدم فيها نوع التعداد، فإننا نستخدم هذا النوع الأساسي. ويُضاف إلى نوع التعداد اختصارٌ برمجي.
  25. 1 2 دار أوباسانجو (2007). "مقارنة بين لغة برمجة سي شارب من مايكروسوفت ولغة برمجة جافا من صن مايكروسيستمز" . دار أوباسانجو. مؤرشف من الأصل في 17 ديسمبر 2001. تم الاطلاع عليه في 6 سبتمبر 2012. في جافا، تُعدّ الأنواع المُعدّدة فئةً كاملةً ، ما يعني أنها آمنة من حيث النوع ويمكن توسيعها بإضافة طرق أو حقول أو حتى تطبيق واجهات. أما في سي شارب، فالنوع المُعدّد هو مجرد اختصار برمجي لنوع صحيح (عادةً ما يكون int)، ما يعني أنه لا يمكن توسيعه وليس آمنًا من حيث النوع.
  26. ^ البروفيسور د. دومينيك جرونتز (8 أبريل 2005). “جافا 5: ترويض النمر: السكر النحوي” (بالألمانية). Fachhochschule أرجاو، نوردويستشفايز. مؤرشفة من الأصلي في 8 يوليو 2012 . تم الاسترجاع 10 سبتمبر 2012 . Enumerationen sind die heimlichen Sieger von Java 1.5. بعد إجراء تحسينات كبيرة خلال Sun، تظهر التعدادات في Java بشكل فائق ويمكن أن يتم تنفيذها بسهولة دون الحاجة إلى إدخالها. يمكن أن يكون التعداد البسيط في السنوات الماضية بمثابة تعداد صحيح لفن خاص من الفصل، وهو تعداد محدد. … يمكن أن أتمكن من استخدام برامج أخرى مثل C/C++ وC# في Gleichheitszeichen التي لا يمكنها تحقيق النجاح.
  27. دار أوباسانجو (2007). "مقارنة بين لغة البرمجة سي شارب من مايكروسوفت ولغة البرمجة جافا من صن مايكروسيستمز: سي. شعور طفيف بالديجا فو: 4. عبارة التبديل" . دار أوباسانجو. مؤرشف من الأصل في 19 سبتمبر 2012. تم الاسترجاع في 10 سبتمبر 2012 .
  28. "goto (C#)" . Msdn.microsoft.com . تم الاطلاع عليه بتاريخ 18 أغسطس 2013 .
  29. ١ ٢ "شبكة أوراكل التقنية لمطوري جافا | شبكة أوراكل التقنية | أوراكل" . Java.sun.com. مؤرشف من الأصل في ٢٧ يونيو ٢٠١٢. تم الاطلاع عليه في ٢٤ فبراير ٢٠١٥ .
  30. كيفية استخدام JavaFX في تطبيق Swing الخاص بك (مؤرشف في 4 مارس 2009 على Wayback Machine)
  31. "التعليمات البرمجية غير الآمنة والمؤشرات (دليل برمجة C#)" . مايكروسوفت . تم الاطلاع عليه بتاريخ 11 مارس 2013 .
  32. "فئة SortedDictionary<TKey,TValue> (System.Collections.Generic)" . learn.microsoft.com . تم الاطلاع عليه بتاريخ 20 أبريل 2023 .
  33. "فئة SortedSet<T> (System.Collections.Generic)" . learn.microsoft.com . تم الاطلاع عليه بتاريخ 20 أبريل 2023 .
  34. "فئة PriorityQueue<TElement,TPriority> (System.Collections.Generic)" . learn.microsoft.com . تم الاطلاع عليه بتاريخ 20 أبريل 2023 .
  35. "System.Collections.Concurrent Namespace" . learn.microsoft.com . تم الاطلاع عليه بتاريخ 20 أبريل 2023 .
  36. "foreach, in (C# reference)" . مايكروسوفت. 2018. مؤرشف من الأصل في 12 يناير 2019. تم الاسترجاع في 26 يناير 2019. تُنفذ عبارة foreach عبارة أو مجموعة عبارات لكل عنصر في مثيل من النوع الذي يُنفذ واجهة System.Collections.IEnumerable أو System.Collections.Generic.IEnumerable<T> .
  37. دار أوباسانجو (2007). "مقارنة بين لغة البرمجة C# من مايكروسوفت ولغة البرمجة Java من صن مايكروسيستمز: C. شعور طفيف بالديجا فو: 6. المجموعات" . دار أوباسانجو. مؤرشف من الأصل في 19 سبتمبر 2012. تم الاسترجاع في 10 سبتمبر 2012. لا يقتصر إطار عمل مجموعات Java على توفير طرق تُمكّن من الوصول إلى المجموعات غير الآمنة بطريقة آمنة للخيوط، بل يحتوي أيضًا على إصدارات آمنة للخيوط لمعظم هياكل البيانات. يتضمن إطار عمل مجموعات Java عددًا من الخوارزميات لمعالجة العناصر داخل هياكل البيانات، بما في ذلك خوارزميات قادرة على القيام بما يلي: إيجاد أكبر عنصر بناءً على مُقارِن، إيجاد أصغر عنصر، إيجاد قوائم فرعية داخل قائمة، عكس محتويات قائمة، خلط محتويات قائمة، إنشاء إصدارات غير قابلة للتغيير من مجموعة، إجراء عمليات الفرز، والبحث الثنائي.
  38. دار أوباسانجو (مارس 2007). "مقارنة بين لغة البرمجة C# من مايكروسوفت ولغة البرمجة Java من صن مايكروسيستمز: C. شعور طفيف بالديجا فو: 6. المجموعات" . دار أوباسانجو . تم الاطلاع عليه في 10 سبتمبر 2012. يتكون إطار عمل مجموعات C# من الفئات الموجودة في مساحتي الأسماء System.Collections وSystem.Collections.Generic. تحتوي مساحة الاسم System.Collections على واجهات وفئات مجردة تمثل أنواع بيانات مجردة مثل IList وIEnumerable وIDictionary وICollection و CollectionBase ، مما يُمكّن المطورين من التعامل مع هياكل البيانات بشكل مستقل عن كيفية تنفيذها فعليًا، طالما أن هياكل البيانات ترث من أنواع البيانات المجردة. تحتوي مساحة الاسم System.Collections أيضًا على بعض التطبيقات الملموسة لهياكل البيانات مثل ArrayList وStack وQueue وHashTable و SortedList . تُمكّن جميع تطبيقات هياكل البيانات الأربعة الملموسة من الحصول على أغلفة متزامنة للمجموعة، مما يسمح بالوصول إليها بطريقة آمنة للخيوط. يحتوي نطاق الاسم System.Collections.Generic على تطبيقات عامة لهياكل البيانات الرئيسية في نطاق الاسم System.Collections، بما في ذلك الفئات العامة List<T> و Stack<T> و Queue<T> و Dictionary<K,T> و SortedDictionary<K,T> .{{cite web}}: CS1 maint: deprecated archiveal service ( link )
  39. "javatuples" . تم الاطلاع عليه بتاريخ 20 أبريل 2023 .
  40. "دمج السلاسل النصية باستخدام $" . learn.microsoft.com. 8 أبريل 2023. تم الاطلاع عليه في 20 أبريل 2023 .
  41. "JEP 378: كتل النصوص" . تم الاطلاع عليه بتاريخ 5 أغسطس 2020 .
  42. دار أوباسانجو (2007). "مقارنة بين لغة البرمجة سي شارب من مايكروسوفت ولغة البرمجة جافا من صن مايكروسيستمز: د. الآن لشيء مختلف تمامًا: 13. السلاسل النصية الحرفية" . دار أوباسانجو. مؤرشف من الأصل في 19 سبتمبر 2012. تم الاسترجاع في 11 سبتمبر 2012 .
  43. إريك فليغال (2004). "تحسين أداء الفاصلة العائمة في مايكروسوفت فيجوال سي++" . MSDN . تم الاطلاع عليه في 1 يناير 2016 .
  44. 1 2 "برنامج عملية مجتمع جافا (SM) - طلبات مواصفات جافا (JSRs): تفاصيل JSR رقم 14" . Jcp.org . تم الاطلاع عليه بتاريخ 24 فبراير 2015 .
  45. "JEP 286: استنتاج نوع المتغير المحلي" . تم الاطلاع عليه بتاريخ 25 أبريل 2018 .
  46. دار أوباسانجو (2007). "مقارنة بين لغة البرمجة سي شارب من مايكروسوفت ولغة البرمجة جافا من صن مايكروسيستمز: د. الآن لشيء مختلف تمامًا: 14. اكتشاف تجاوز السعة" . مؤرشف من الأصل في 22 سبتمبر 2012. تم الاطلاع عليه في 11 سبتمبر 2012 .
  47. "JEP 306: استعادة دلالات الفاصلة العائمة الصارمة دائمًا" .
  48. دار أوباسانجو (2007). "مقارنة بين لغة البرمجة سي شارب من مايكروسوفت ولغة البرمجة جافا من صن مايكروسيستمز: شعور طفيف بالديجا فو: 4. عبارة التبديل [ كذا ] " . مؤرشف من الأصل في 22 سبتمبر 2012. تم الاطلاع عليه في 7 سبتمبر 2012 .
  49. "عبارة try-with-resources (دروس جافا > الفئات الأساسية > الاستثناءات)" . Docs.oracle.com. 28 فبراير 2012. تم الاطلاع عليه بتاريخ 24 فبراير 2015 .
  50. تم إنشاء إضافة للغة البرمجة جافا
  51. "الأنواع المجهولة (أساسيات لغة C#)" . learn.microsoft.com . تم الاطلاع عليه بتاريخ 14 أبريل 2013 .
  52. "مواصفات Java SE" . Java.sun.com . تم الاطلاع عليه بتاريخ 24 فبراير 2015 .
  53. دار أوباسانجو (2007). "مقارنة بين لغة برمجة C# من مايكروسوفت ولغة برمجة Java من صن مايكروسيستمز: تحميل المعاملات الزائد" . دار أوباسانجو. مؤرشف من الأصل في 19 سبتمبر 2012. تم الاسترجاع في 6 سبتمبر 2012. ملاحظة: على عكس C++، لا تسمح C# بتحميل المعاملات الزائدة التالية: new، ( )، | | ، &&، = ، أو أي اختلافات في عمليات الإسناد المركبة مثل +=، -= ، إلخ. ومع ذلك، ستستدعي معاملات الإسناد المركبة المعاملات المحملة بشكل زائد، على سبيل المثال، سيستدعي + = المعامل + المحمل بشكل زائد .
  54. "أخبار جافا من أغسطس 1998" . Cafeaulait.org . تم الاطلاع عليه بتاريخ 24 فبراير 2015 .
  55. سونولد، كوري (25 فبراير 2010). "مكافئ لغة C# لـ "final" في لغة Java"« . كوري سونولد . تم الاطلاع عليه بتاريخ 13 سبتمبر 2016. » هناك أكثر من استخدام للكلمة المفتاحية final لا يوجد له مكافئ في لغة C#. عند تمرير مُعامل إلى دالة في Java، ولا ترغب في تغيير قيمة هذا المُعامل ضمن نطاق تلك الدالة، يمكنك تعيينه كـ final كما يلي:{{cite web}}: CS1 maint: deprecated archiveal service ( link )
  56. "معاينة لغة C# – AC# 6.0" . learn.microsoft.com. يوليو 2015. تم الاطلاع عليه في 14 أبريل 2023 .
  57. 1 2 دار أوباسانجو (2007). "مقارنة بين لغة البرمجة سي شارب من مايكروسوفت ولغة البرمجة جافا من صن مايكروسيستمز: د. الآن لشيء مختلف تمامًا: 15. تنفيذ الواجهة الصريحة" . دار أوباسانجو. مؤرشف من الأصل في 22 سبتمبر 2012. تم الاسترجاع في 11 سبتمبر 2012 .
  58. "مُعدِّل المعامل في (مرجع C#)" . مايكروسوفت. 5 مارس 2018. تم الاطلاع عليه بتاريخ 26 يناير 2019 .{{cite web}}: CS1 maint: deprecated archiveal service ( link )
  59. جوسلينج، جيمس. "مواصفات لغة جافا®" . القسم 8.4.1. المعلمات الرسمية . تم الاطلاع عليه بتاريخ 5 أكتوبر 2014 .{{cite web}}: CS1 maint: location ( link )
  60. هانسيلمان، سكوت (4 أبريل 2008). "كيف تعمل أساليب الإضافة ولماذا لم تكن هناك حاجة إلى بيئة تشغيل لغة مشتركة جديدة؟" . تم الاطلاع عليه في 29 مارس 2014. أساليب الإضافة هي اختصار برمجي رائع. لا تُضاف فعليًا إلى الفئة، كما نرى، لكن المُصرّف يُوهمنا بأنها كذلك .
  61. "أساليب الإضافة (دليل برمجة C#)" . مايكروسوفت . 2013. تم الاطلاع عليه بتاريخ 29 مارس 2014. تُعرَّف أساليب الإضافة على أنها أساليب ثابتة، ولكن يتم استدعاؤها باستخدام صيغة أسلوب الكائن .
  62. " مواصفات لغة C# الإصدار 4.0" . مايكروسوفت. ص 281. تم الاطلاع عليه في 10 مايو 2012. إذا لم يتضمن أي جزء من تعريف النوع الجزئي تعريفًا تنفيذيًا لطريقة جزئية معينة، فسيتم ببساطة إزالة أي عبارة تعبيرية تستدعيها من تعريف النوع المدمج. وبالتالي، فإن تعبير الاستدعاء، بما في ذلك أي تعبيرات مكونة له، لن يكون له أي تأثير في وقت التشغيل. كما تتم إزالة الطريقة الجزئية نفسها ولن تكون عضوًا في تعريف النوع المدمج. إذا كان هناك تعريف تنفيذي لطريقة جزئية معينة، فسيتم الاحتفاظ باستدعاءات الطرق الجزئية. تُنشئ الطريقة الجزئية تعريفًا للطريقة مشابهًا لتعريف الطريقة الجزئية التنفيذية باستثناء ما يلي: [...] 
  63. "مُعدِّل المعامل in (مرجع C#)" . مايكروسوفت. 5 مارس 2018. تاريخ الاسترجاع: 26 يناير 2019. تُمرِّر الكلمة المفتاحية in الوسائط بالمرجع. وهي تُشبه الكلمتين المفتاحيتين ref و out، باستثناء أن الوسائط in لا يُمكن تعديلها بواسطة الدالة المُستدعاة.{{cite web}}: CS1 maint: deprecated archiveal service ( link )
  64. دار أوباسانجو (2007). "مقارنة بين لغة البرمجة C# من مايكروسوفت ولغة البرمجة Java من صن مايكروسيستمز: د. الآن لشيء مختلف تمامًا: 12. التمرير بالمرجع" . دار أوباسانجو. مؤرشف من الأصل في 19 سبتمبر 2012. تم الاسترجاع في 10 سبتمبر 2012. في Java، تُمرر وسائط الدالة بالقيمة، مما يعني أن الدالة تعمل على نسخ من العناصر المُمررة إليها بدلًا من العناصر الأصلية. في C#، كما هو الحال في C++، وبمعنى ما في C، من الممكن تحديد أن وسائط الدالة هي في الواقع مراجع للعناصر المُمررة إليها بدلًا من نسخها. تُعد هذه الميزة مفيدة بشكل خاص عند الرغبة في إنشاء دالة تُرجع أكثر من كائن واحد. في لغة جافا، محاولة إرجاع قيم متعددة من دالة غير مدعومة وتؤدي إلى حالات شاذة مثل: دالة تقوم بتبديل رقمين كانت السمة المميزة لفصول علوم الحاسوب للمبتدئين لسنوات، من المستحيل القيام بذلك في جافا دون اللجوء إلى حيل البرمجة.
  65. "تصفية الاستثناءات الاستثنائية" . Pluralsight® . تم الاطلاع عليه بتاريخ 24 يونيو 2022 .
  66. "مشكلة الاستثناءات المُدققة" . Artima.com . تم الاطلاع عليه بتاريخ 24 فبراير 2015 .
  67. "منتديات MSDN - لغة Visual C#" . Msdn2.microsoft.com. مؤرشف من الأصل بتاريخ 20 مارس 2007. تم الاطلاع عليه بتاريخ 24 فبراير 2015 .
  68. إيكل، بروس. "هل تحتاج جافا إلى استثناءات مُدققة؟" . مؤرشف من الأصل في 5 أبريل 2002. تم الاطلاع عليه في 6 ديسمبر 2012 .
  69. "الفشل والاستثناءات" . Artima.com. 22 سبتمبر 2003. تم الاطلاع عليه بتاريخ 18 أغسطس 2013 .
  70. "الاستثناءات المُدققة" . شون أبرام . تم الاطلاع عليه بتاريخ 18 أغسطس 2013 .
  71. "مواصفات Java SE" . Java.sun.com . تم الاطلاع عليه بتاريخ 24 فبراير 2015 .
  72. أنجليكا لانجر. "أسئلة وأجوبة شائعة حول Java Generics - التدريب والاستشارات مع أنجليكا لانجر" . AngelikaLanger.com . تاريخ الاطلاع: 24 فبراير 2015 .
  73. أنجليكا لانجر (16 أبريل 2013). "أسئلة وأجوبة حول البرمجة العامة في جافا - نظرة معمقة على المُصرّف - تدريب واستشارات أنجليكا لانجر" . AngelikaLanger.com . تاريخ الاطلاع: 18 أغسطس 2013 .
  74. أنجليكا لانجر (16 أبريل 2013). "أسئلة وأجوبة حول البرمجة العامة في جافا - نظرة معمقة على المُصرّف - تدريب واستشارات أنجليكا لانجر" . AngelikaLanger.com . تاريخ الاطلاع: 18 أغسطس 2013 .
  75. أنجليكا لانجر (16 أبريل 2013). "أسئلة وأجوبة حول البرمجة العامة في جافا - نظرة معمقة على المُصرّف - تدريب واستشارات أنجليكا لانجر" . AngelikaLanger.com . تاريخ الاطلاع: 18 أغسطس 2013 .
  76. أنجليكا لانجر (13 فبراير 2014). "أسئلة وأجوبة حول Java Generics - معلمات النوع - تدريب/استشارات أنجليكا لانجر" . AngelikaLanger.com . تم الاطلاع عليه بتاريخ 24 فبراير 2015 .
  77. "الأنواع العامة في لغات C# و Java و C" . Artima.com . تم الاطلاع عليه بتاريخ 24 فبراير 2015 .
  78. "trove4j / Trove" . تم الاطلاع عليه بتاريخ 30 يونيو 2017 .
  79. نيل غافتر (23 سبتمبر 2004). "مدونة نيل غافتر: حل الألغاز من خلال المحو: قسم الإجابات" . Gafter.blogspot.com . تاريخ الاسترجاع: 18 أغسطس 2013 .
  80. "مراجع الأساليب (دروس جافا > تعلم لغة جافا > الفئات والكائنات)" . Docs.oracle.com. 28 فبراير 2012. تم الاطلاع عليه بتاريخ 24 فبراير 2015 .
  81. "تعبيرات لامدا (دروس جافا > تعلم لغة جافا > الفئات والكائنات)" . Docs.oracle.com. 28 فبراير 2012. تم الاطلاع عليه بتاريخ 24 فبراير 2015 .
  82. "درس: عمليات التجميع (دروس جافا > المجموعات)" . Docs.oracle.com. 28 فبراير 2012. تم الاطلاع عليه بتاريخ 24 فبراير 2015 .
  83. برونو، إريك (7 نوفمبر 2022). "الأقواس المعقوفة #6: الاستدعاء الذاتي وتحسين استدعاء الذيل" . مؤرشف من الأصل في 17 يوليو 2024. تم الاسترجاع في 17 يوليو 2024 .
  84. جرانت ريتشينز (11 مايو 2009). "تحسينات استدعاء الذيل في إطار عمل .NET 4" . مدونات MSDN .
  85. ريختر، جيفري (أبريل 2001). "مقدمة عن المندوبين" . مجلة MSDN . تم الاطلاع عليه بتاريخ 23 ديسمبر 2008 .
  86. كامبل، داستن (9 فبراير 2007). "ماذا تعني كلمة Closure؟" . تم إنجاز ذلك باستخدام .NET . مؤرشف من الأصل في 15 أغسطس 2014. تم الاطلاع عليه في 23 ديسمبر 2008 .
  87. دار أوباسانجو (2007). "مقارنة بين لغة برمجة C# من مايكروسوفت ولغة برمجة Java من صن مايكروسيستمز: تعليقات البيانات الوصفية" . دار أوباسانجو. مؤرشف من الأصل في 19 سبتمبر 2012. تم الاطلاع عليه في 6 سبتمبر 2012. مع ذلك، يتمثل أحد الاختلافات الرئيسية بين سمات C# وتعليقات Java في إمكانية إنشاء تعليقات وصفية (أي تعليقات على التعليقات) في Java، بينما لا يمكن فعل الشيء نفسه في C#. يستطيع المطورون إنشاء تعليقاتهم المخصصة عن طريق إنشاء نوع تعليق مشابه للواجهة، باستثناء استخدام الكلمة المفتاحية @interface لتعريفه.
  88. "عنصر" . Msdn.microsoft.com . تم الاطلاع عليه بتاريخ 18 أغسطس 2013 .
  89. "تجميع C# - مسار مرجعي مخصص - Visual C# Kicks" . Vcskicks.com . تم الاطلاع عليه بتاريخ 18 أغسطس 2013 .
  90. إطار عمل Fork-join مُضمّن في إصدار Java 7. "ForkJoinPool (Java Platform SE 7)" . أوراكل . تم الاطلاع عليه بتاريخ 17 يوليو 2015 .
  91. "مكتبة المهام المتوازية (TPL)" . Msdn.microsoft.com. ١٨ فبراير ٢٠١٥. تم الاطلاع عليه بتاريخ ٢٤ فبراير ٢٠١٥ .
  92. "جافا للحوسبة العلمية : الآفاق والمشاكل" (ملف PDF) . Pds.ewi.tudelft.nl. مؤرشف من النسخة الأصلية (ملف PDF) بتاريخ 22 سبتمبر 2007. تم الاطلاع عليه بتاريخ 24 فبراير 2015 . 
  93. " مواصفات لغة C# الإصدار 5.0" . مايكروسوفت. 4.1.6 أنواع الأعداد العشرية . تم الاطلاع عليه بتاريخ 28 أكتوبر 2013. يمكن إجراء عمليات الأعداد العشرية بدقة أعلى من نوع نتيجة العملية. على سبيل المثال، تدعم بعض بنى الأجهزة نوع "extended" أو "long double" للأعداد العشرية بنطاق ودقة أكبر من نوع double، وتُجري ضمنيًا جميع عمليات الأعداد العشرية باستخدام هذا النوع ذي الدقة الأعلى. لا يمكن جعل هذه البنى تُجري عمليات الأعداد العشرية بدقة أقل إلا بتكلفة باهظة في الأداء ، وبدلاً من اشتراط التضحية بالأداء والدقة معًا، تسمح لغة C# باستخدام نوع ذي دقة أعلى لجميع عمليات الأعداد العشرية. وباستثناء تقديم نتائج أكثر دقة، نادرًا ما يكون لهذا أي تأثيرات قابلة للقياس. ومع ذلك، في التعبيرات من الشكل x*y/z، حيث ينتج عن الضرب نتيجة خارج نطاق المضاعفة، ولكن القسمة اللاحقة تعيد النتيجة المؤقتة إلى نطاق المضاعفة، فإن حقيقة تقييم التعبير بتنسيق نطاق أعلى قد تتسبب في إنتاج نتيجة محدودة بدلاً من اللانهاية.
  94. "العدد العشري مقابل 110" . تم الاطلاع عليه بتاريخ 24 فبراير 2015 .
  95. "مواصفات لغة C# الإصدار 5.0" . مايكروسوفت. 4.1.7 النوع العشري.
  96. "معقد" . تم الاطلاع عليه بتاريخ 24 فبراير 2015 .
  97. "JEP 454: دالة خارجية وواجهة برمجة تطبيقات الذاكرة" . أوراكل.
  98. "ECMA-335 البنية التحتية للغة المشتركة" . ECMA.
  99. "مواصفات واجهة جافا الأصلية" . أوراكل.
  100. "JEP 454: دالة خارجية وواجهة برمجة تطبيقات الذاكرة" . أوراكل.
  101. "خدمات استدعاء النظام الأساسي (P/Invoke)" . مايكروسوفت.
  102. "JEP 454: دالة خارجية وواجهة برمجة تطبيقات الذاكرة" . أوراكل.
  103. "عملية تحويل البيانات في .NET" . مايكروسوفت.
  104. "JEP 454: دالة خارجية وواجهة برمجة تطبيقات الذاكرة" . أوراكل.
  105. "مواصفات لغة C# ECMA-334" . ECMA.
  106. "JEP 454: دالة خارجية وواجهة برمجة تطبيقات الذاكرة" . أوراكل.
  107. ^ "مارشال.AllocHGlobal" . مايكروسوفت.
  108. "JEP 454: دالة خارجية وواجهة برمجة تطبيقات الذاكرة" . أوراكل.
  109. "كلمة مفتاحية stackalloc" . مايكروسوفت.
  110. "مواصفات لغة جافا" . أوراكل.
  111. "مواصفات لغة C# ECMA-334" . ECMA.
  112. "JEP 454: دالة خارجية وواجهة برمجة تطبيقات الذاكرة" . أوراكل.
  113. "بنية GCHandle" . مايكروسوفت.
  114. "JEP 454: دالة خارجية وواجهة برمجة تطبيقات الذاكرة" . أوراكل.
  115. "مؤشرات الدوال في لغة C#" . مايكروسوفت.
  116. "JEP 454: دالة خارجية وواجهة برمجة تطبيقات الذاكرة" . أوراكل.
  117. "تخطيط البنية الصريح" . مايكروسوفت.
  118. "مشروع بنما" . OpenJDK.
  119. "واجهة برمجة تطبيقات الوظائف الخارجية والذاكرة" . أوراكل.