بناء جملة لغة سي شارب

تشرح هذه المقالة بنية لغة البرمجة C# . وتتوافق الميزات المذكورة مع إطار عمل .NET و Mono .
الأساسيات
المعرف
المعرّف هو اسم عنصر برمجي. يمكن أن يحتوي على حروف وأرقام وشرطات سفلية ( )، وهو حساس لحالة الأحرف ( يختلف عن ) . تفرض اللغة القيود التالية على أسماء المعرّفات:_FOOfoo
- لا يمكن أن تبدأ برقم؛
- لا يمكن أن تبدأ برمز، باستثناء علامة @ (
@)، والتي يمكن استخدامها كبادئة للكلمات الرئيسية للسماح بها كمعرفات؛ - لا يمكن أن تحتوي على أكثر من 511 حرفًا .
قد تُسبق أسماء المعرفات بـ @، مما يسمح باستخدام الكلمات المحجوزة كمعرفات (على سبيل المثال، @class)، ولكن @لا يُعتبر جزءًا من اسم المعرف لمعظم الأغراض؛ @nameوتشير nameإلى نفس المعرف.
قدّمت مايكروسوفت اصطلاحات تسمية للمعرفات في لغة C#، موصيةً باستخدام PascalCase لأسماء الأنواع ومعظم عناصرها، و camelCase للمتغيرات والحقول الخاصة أو الداخلية. [ 1 ] لا تفرض اللغة هذه الاصطلاحات.
الكلمات المفتاحية
الكلمات المفتاحية هي كلمات ذات معنى نحوي. [ 2 ] تحتوي اللغة على نوعين من الكلمات المفتاحية : كلمات سياقية وكلمات محجوزة. الكلمات المحجوزة، مثل false`or`، byteلا تُستخدم إلا ككلمات مفتاحية. أما الكلمات السياقية، مثل where`or` from، فتُعامل ككلمات مفتاحية في حالات معينة فقط. [ 3 ] إذا لزم مُعرِّف يُطابق كلمة مفتاحية محجوزة، يُسبق بعلامة @ لتمييزه. على سبيل المثال، @outيُفسَّر `or` كمُعرِّف، بينما out`or` كلمة مفتاحية. يُسهِّل هذا التركيب إعادة استخدام كود .NET المكتوب بلغات أخرى. [ 4 ]
الكلمات الرئيسية التالية في لغة C# هي كلمات محجوزة، ويبلغ عددها 77 كلمة. [ 2 ]
abstractasbaseboolbreakbytecasecatchcharcheckedclassconstcontinuedecimaldefaultdelegatedodoubleelseenumeventexplicitexternfalsefinallyfixedfloatforforeachgotoifimplicitinintinterfaceinternalislocklongnamespacenewnullobjectoperatoroutoverrideparamsprivateprotectedpublicreadonlyrefreturnsbytesealedshortsizeofstackallocstaticstringstructswitchthisthrowtruetrytypeofuintulonguncheckedunsafeushortusingvirtualvoidvolatilewhile
الكلمات المفتاحية السياقية
تُستخدم الكلمات المفتاحية السياقية لإضفاء معنى محدد على الكود، ولكنها ليست كلمات محجوزة في لغة C#. بعض الكلمات المفتاحية السياقية، مثل ` partialand` where، لها معانٍ في سياقات متعددة. فيما يلي 42 كلمة مفتاحية سياقية في لغة C#. [ 5 ]
addallowsaliasandascendingargsasyncawaitbydescendingdynamicequalsfromgetglobalgroupinitintojoinletmanagednameofnintnotnotnullnuintonororderbypartialrecordremoverequiredselectsetunmanagedvaluevarwhenwherewithyield
توجيهات المعالج المسبق
على الرغم من أن لغة C# لا تحتوي على معالج مسبق منفصل ، على عكس لغتي C و C++ اللتين تستخدمان المعالج المسبق C ، إلا أن هذه التوجيهات الـ 13 تتم معالجتها كما لو كان هناك واحد.
#nullable#if#elif#else#endif#define#undef#region#endregion#error#warning#line#pragma
حرفيًا
| عشري | 23456,[0..9]+ |
|---|---|
| النظام الست عشري | 0xF5,0x[0..9,A..F,a..f]+ |
| ثنائي | 0b010110001101,0b[0,1]+ |
| يطفو | 23.5F,23.5f;1.72E3F,1.72E3f,1.72e3F,1.72e3f |
|---|---|
| مزدوج | 23.5,23.5D,23.5d;1.72E3,1.72E3D,... |
| عشري | 79228162514264337593543950335m,-0.0000000000000000000000000001m,... |
| شخصية | 'a','Z','\u0231','\x30','\n' |
|---|
| خيط | "Hello, world""C:\\Windows\\"[ قد تتضمن السلاسل النصية الحرفية (المسبوقة بـ @) أحرف فاصل الأسطر وإرجاع المؤشر إلى بداية السطر] سلسلة نصية مُدمجة. كسلسلة نصية حرفية:@"C:\Windows\"$"Hello, {name}!"$@"Hello, {name}!" |
|---|
| حرف يونيكود | \uمتبوعًا بنقطة رمز يونيكود السداسي العشري |
|---|---|
| حرف ASCII الموسع | \xمتبوعًا بنقطة رمز ASCII الموسع الست عشري |
| الحرف الفارغ [ a ] | \0حرف فارغ |
| فاتورة غير مدفوعة | \tفاتورة غير مدفوعة |
| مسافة للخلف | \bمسافة للخلف |
| إرجاع السطر | \rإرجاع المؤشر إلى بداية السطر الحالي |
| تغذية النموذج | \fتغذية النموذج (فاصل الصفحات) |
| رد فعل عكسي | \\رد فعل عكسي |
| اقتباس واحد | \'اقتباس واحد |
| علامات اقتباس مزدوجة | \"علامات اقتباس مزدوجة |
| تغذية السطر | \nنقل السطر (ينقل المؤشر إلى السطر التالي) |
- ↑ لا تنتهي السلاسل النصية بحرف فارغ في لغة C#، لذا قد تظهر الأحرف الفارغة في أي مكان في السلسلة النصية.
فواصل الأرقام
ابتداءً من الإصدار 7.0 من لغة C#، يمكن استخدام رمز الشرطة السفلية لفصل الأرقام في القيم العددية لأغراض سهولة القراءة. ويتجاهل المترجم هذه الشرطات السفلية. [ 6 ]
int bin = 0b1101_0010_1011_0100 ; int hex = 0x2F_BB_4A_F1 ; int dec = 1_000_500_954 ; double real = 1_500.200_2e - 1_000 ;بشكل عام، لا يجوز وضع الفواصل إلا بين الأرقام. ولا يمكن وضعها في بداية _121القيمة ( ) أو نهايتها ( 121_أو 121.05_)، أو بجوار الفاصلة العشرية في قيم الفاصلة العائمة ( 10_.0)، أو بجوار رمز الأس ( 1.1e_1)، أو بجوار مُحدد النوع ( 10_f).
المتغيرات
المتغيرات هي مُعرِّفات مرتبطة بالقيم. يتم تعريفها بكتابة نوع المتغير واسمه، ويمكن تهيئتها اختيارياً في نفس العبارة. [ 10 ] [ 11 ]
يعلن
int myInt ; // تعريف متغير غير مهيأ يسمى 'myInt'، من النوع 'int'التعيين
int myInt ; // تعريف متغير غير مهيأ myInt = 35 ; // إسناد قيمة للمتغيرتهيئة
int myInt = 35 ; // تعريف وتهيئة المتغيريمكن تعريف وتهيئات متغيرات متعددة من نفس النوع في عبارة واحدة.
int a , b ; // تعريف متغيرات متعددة من نفس النوعint a = 2 , b = 3 ; // تعريف وتهيئة متغيرات متعددة من نفس النوعاستنتاج نوع المتغير المحلي
- هذه ميزة من ميزات لغة C# 3.0 .
قدّمت لغة C# 3.0 ميزة استنتاج النوع ، مما يسمح باستبدال مُحدِّد نوع تعريف المتغير بالكلمة المفتاحية var، إذا أمكن تحديد نوعه الفعلي بشكل ثابت من المُهيئ. هذا يقلل من التكرار، خاصةً للأنواع ذات مُعاملات النوع العامة المتعددة ، ويتوافق بشكل أكبر مع مبدأ DRY (لا تُكرِّر نفسك) .
var myChars = new char [] { 'A' , 'Ö' }; // مكافئ لـ: char [] myChars = new char [] { 'A' , 'Ö' };var myNums = new List <int> ( ) ; // مكافئ لـ : List <int> myNums = new List <int> ( ) ;الثوابت
الثوابت هي قيم غير قابلة للتغيير.
const
عند تعريف متغير محلي أو حقل باستخدام constالكلمة المفتاحية كبادئة، يجب تحديد قيمته عند التعريف. بعد ذلك، لا يمكن تغيير القيمة. يمكن تعريفها في السياق كحقل أو كمتغير محلي. [ 10 ] الثوابت ثابتة ضمنيًا.
const double PI = 3.14 ;هذا يوضح كلا استخدامي الكلمة المفتاحية.
public class Foo { private const double X = 3 ;public Foo () { const int y = 2 ; } }readonly
تؤدي الكلمة readonlyالمفتاحية وظيفة مشابهة للحقول. فالحقول التي تم تحديد constقيمتها لا يمكن تغييرها بعد تهيئتها. والفرق هو أنه يمكن اختيار تهيئتها في الدالة البانية، أو بقيمة غير معروفة حتى وقت التشغيل. [ 12 ] هذا ينطبق فقط على الحقول. readonlyيمكن أن تكون الحقول إما أعضاءً في مثيل أو أعضاءً ثابتة في فئة.
كتل التعليمات البرمجية
تُستخدم الأقواس المعقوفة للدلالة على كتلة برمجية ونطاق جديد . أعضاء الفئة وجسم الدالة هما مثالان على ما يمكن أن يوجد داخل هذه الأقواس في سياقات مختلفة.{...}
داخل أجسام الدوال، يمكن استخدام الأقواس لإنشاء نطاقات جديدة:
void DoSomething () { int a ;{ int b ; a = 1 ; }a = 2 ; b = 3 ; // سيفشل هذا لأن المتغير مُعرَّف في نطاق داخلي. }هيكل البرنامج
يتكون تطبيق AC# من فئات وأعضائها. توجد الفئات والأنواع الأخرى في مساحات أسماء ويمكن تضمينها داخل فئات أخرى.
الطريقة الرئيسية
يجب أن يحتوي كل برنامج على نقطة دخول. نقطة دخول تطبيق C# هي الدالة Main. لا يمكن تعريف هذه الدالة إلا مرة واحدة، وهي دالة ثابتة في الصنف. عادةً ما تُرجع هذه الدالة voidوسيطات سطر الأوامر، ويتم تمريرها كمصفوفة من السلاسل النصية.
static void Main ( string [] args ) // يمكن حذف string[] args إذا لم يكن للبرنامج أي وسائط سطر أوامر. { }قد تُرجع الدالة الرئيسية قيمة عددية صحيحة إذا تم تحديد ذلك.
static int Main ( string [] args ) { return 0 ; }Async Main
هذه ميزة من ميزات لغة C# 7.1.
يمكن انتظار المهام غير المتزامنة في Mainالطريقة عن طريق تعريف نوع الإرجاع الخاص بالطريقة على أنه Task.
static async Task Main ( string [] args ) { await DoWorkAsync ( 42 ); }جميع تركيبات Task، أو Task<int>,و مع أو بدون string[] argsالمعلمة مدعومة.
بيانات رفيعة المستوى
هذه ميزة من ميزات لغة C# 9.0.
على غرار لغات البرمجة النصية ، تعمل العبارات ذات المستوى الأعلى على إزالة مراسم تعريف Programالفئة باستخدام Mainطريقة.
بدلاً من ذلك، يمكن كتابة التعليمات البرمجية مباشرةً في ملف واحد، وهو نقطة دخول البرنامج. أما التعليمات البرمجية في الملفات الأخرى فيجب تعريفها في فئات.
تم إدخال هذا لجعل لغة C# أقل إسهاباً، وبالتالي أكثر سهولة في الوصول إليها.
باستخدام النظام ؛Console.WriteLine ( "Hello World! " ) ;يتم تعريف الأنواع بعد العبارات، وتكون متاحة من العبارات التي تسبقها.
مساحات الأسماء
تُعد مساحات الأسماء جزءًا من اسم النوع وتستخدم لتجميع و/أو تمييز الكيانات المسماة عن غيرها.
System.IO.DirectoryInfo // DirectoryInfo موجود في مساحة اسم System.IOيتم تعريف مساحة الاسم باستخدام الكلمة المفتاحية namespace:
namespace FooNamespace { // الأعضاء }يمكن تضمين مساحة اسم داخل مساحة اسم بثلاث طرق:
namespace FooNamespace { // الأعضاء namespace BarNamespace { // الأعضاء } }و:
namespace FooNamspace { // الأعضاء }namespace FooNamspace.BarNamespace { // الأعضاء }في C# 10 والإصدارات الأحدث، يمكن تعريف مساحات الأسماء باستخدام التصريحات ذات النطاق الملفي عن طريق القيام بما يلي: [ 13 ]
namespace FooNamespace ; // تم حذف الأقواس هنا لصالح الفاصلة المنقوطة.usingتوجيه
يقوم هذا usingالتوجيه بتحميل مساحة اسم محددة من تجميعة مرجعية. وعادةً ما يوضع في أعلى ملف التعليمات البرمجية (أو في قسم الرأس)، ولكن يمكن وضعه في مكان آخر، مثلاً داخل فئة.
باستخدام System ؛ باستخدام System.Collections ؛يمكن استخدام هذا التوجيه أيضًا لتعريف اسم آخر لمساحة اسم أو نوع موجود. وهذا مفيد عندما تكون الأسماء طويلة.
باستخدام Net = System.Net ؛ باستخدام DirInfo = System.IO.DirectoryInfo ؛usingstaticتوجيه
يقوم التوجيه بتحميل الأعضاء الثابتة من نوع محدد في النطاق الحالي، مما يجعلها قابلة للوصول إليها مباشرة عن طريق اسم العضو.usingstatic
باستخدام النظام الثابت . وحدة التحكم ؛WriteLine ( “Hello, World!” );globalusingتوجيه
منذ إصدار C# 10، أصبح من القانوني كتابة التوجيهات للإشارة إلى توجيه ما مرة واحدة وتطبيقه على جميع ملفات المصدر.globalusingusing
استخدام النظام بشكل عام ؛ استخدام Microsoft.Extensions.FileSystemGlobbing بشكل عام ؛المشغلون
| فئة المشغل | المشغلون |
|---|---|
| الحساب | +، -، *، /،% |
| منطقي (بولياني وبتوي) | &، |، ^، !، ~، &&، ، ||، true،false |
| دمج السلاسل | + |
| زيادة، نقصان | ++،-- |
| يحول | <<،>> |
| العلاقات (الشرطية) | ==، !=، <، >، <=،>= |
| تكليف | =، +=، -=، *=، /=، %=، &=، |=، ، ^=، <<=،>>= |
| وصول الأعضاء | .، ?.،?[] |
| الفهرسة | [] |
| يقذف | () |
| الشرطي (الثلاثي) | ?: |
| دمج المفوضين وإزالتهم | +،- |
| إنشاء الكائنات | new |
| اكتب المعلومات | as، is، sizeof،typeof |
| التحكم في استثناء تجاوز السعة | checked،unchecked |
| التوجيه غير المباشر والتوجيه | *، ->، []،& |
| اندماج | ?? |
| تعبير لامدا | => |
إرهاق المشغل
يمكن إعادة تعريف بعض المعاملات عن طريق كتابة دالة إعادة تعريف.
public static Foo operator + ( Foo foo , Bar bar ) { return new Foo ( foo . Value + bar . Value ); }هذه هي عوامل التشغيل القابلة للتحميل الزائد :
| المشغلون | |
|---|---|
+، -، !، ~، ++، ، --، true،false | المعاملات الأحادية |
+، -، *، /، %، &، |، ، ^، <<،>> | المعاملات الثنائية |
==، !=، <، >، <=،>= | يجب تحميل عوامل المقارنة بشكل زائد في أزواج |
- عوامل التعيين ( إلخ) هي عبارة عن مجموعات من عامل ثنائي وعامل التعيين ( ) ويتم تقييمها باستخدام العوامل العادية، والتي يمكن تحميلها بشكل زائد.
+=,*== - لا يمكن تحميل عوامل التحويل ( ) بشكل زائد، ولكن من الممكن تعريف عوامل التحويل.
() - لا يمكن تحميل عامل فهرسة المصفوفة (
[ ]) بشكل زائد، ولكن من الممكن تعريف فهارس جديدة.
مشغلي التحويل
لا يمكن تحميل عامل التحويل بشكل زائد، ولكن يمكن أن توجد دالة عامل التحويل في الفئة المستهدفة. يمكن لدوال التحويل تعريف نوعين من عوامل التحويل: عوامل التحويل الضمنية وعوامل التحويل الصريحة. يقوم عامل التحويل الضمني بالتحويل دون تحديد باستخدام عامل التحويل ( )، بينما يتطلب عامل التحويل الصريح استخدامه.()
عامل التحويل الضمني
class Foo { public int Value ;public static implicit operator Foo ( int value ) { return new Foo ( value ); } } // Implicit conversion Foo foo = 2 ;عامل التحويل الصريح
class Foo { public int Value ;public static explicit operator Foo ( int value ) { return new Foo ( value ); } } // تحويل صريح Foo foo = ( Foo ) 2 ;asمشغل
سيحاول المُعامل asإجراء تحويل صامت إلى نوع مُحدد. وسيعيد الكائن بالنوع الجديد إن أمكن، وإلا فسيعيد قيمة فارغة (null).
Stream stream = File.Open ( @ "C:\Temp\data.dat" ); FileStream fstream = stream as FileStream ; // سيعيد كائنًا.String str = stream as String ; // ستُرجع قيمة فارغة (null).عامل دمج القيم الفارغة
- هذه ميزة من ميزات لغة C# 2.0 .
ما يلي:
أعد القيمة إذا لم تكن فارغة، وإلا فأعد القيمة .هو اختصار لـ:
أرجع إذا لم تكن القيمة فارغة (ifNotNullValue != null ) إذا كانت القيمة فارغة (ifNotNullValue : otherwiseValue ;بمعنى أنه إذا لم يكن محتوى المتغير فارغًا، فسيتم إرجاع هذا المحتوى، وإلا فسيتم إرجاع ifNotNullValueمحتوى المتغير .otherwiseValue
يُقدّم الإصدار 8.0 من لغة C# ميزة دمج القيم الفارغة في عملية الإسناد ، بحيث
المتغير ??= القيمة الأخرى ;يعادل
إذا كانت قيمة المتغير فارغة ، فسيتم تعيين قيمة المتغير إلى القيمة الأخرى .هياكل التحكم
ترث لغة C# معظم هياكل التحكم الخاصة بلغة C/C++ وتضيف إليها هياكل أخرى مثل foreachالعبارة.
الهياكل الشرطية
تتحكم هذه الهياكل في تدفق البرنامج من خلال شروط معينة.
ifإفادة
يتم إدخال العبارة ifعندما يكون الشرط المحدد صحيحًا. لا تتطلب عبارات الحالة ذات السطر الواحد أقواسًا متداخلة، على الرغم من أنها تُفضّل في الغالب وفقًا للعرف.
عبارة بسيطة من سطر واحد:
إذا كان ( i == 3 ) ... ؛متعدد الأسطر مع كتلة else (بدون أي أقواس):
إذا كان ( i == 2 ) ... وإلا ...قواعد البرمجة الموصى بها لعبارة if.
إذا كان ( i == 3 ) { ... } وإلا إذا كان ( i == 2 ) { ... } وإلا { ... }switchإفادة
يُستخدم هذا switchالتركيب كمرشح للقيم المختلفة. كل قيمة تؤدي إلى "حالة". لا يُسمح بالانتقال بين أقسام الحالات، ولذلك breakتُستخدم الكلمة المفتاحية عادةً لإنهاء حالة. returnيمكن أيضًا استخدام شرط غير مشروط في قسم الحالة لإنهاء حالة. gotoيمكن استخدام عبارات للانتقال من حالة إلى أخرى. تعالج الحالة الافتراضية جميع الحالات التي لم يُعالجها التركيب صراحةً.
switch ( ch ) { case 'A' : statement ; ... break ; case 'B' : statement ; break ; case 'C' : // يمكن أن يحتوي قسم switch على عدة تسميات case. case 'D' : ... break ; default : ... break ; }هياكل التكرار
عبارات التكرار هي عبارات يتم تنفيذها بشكل متكرر عندما يتم تقييم شرط معين على أنه صحيح.
whileحلقة
بينما ( i == صحيح ) { ... }do ... whileحلقة
يفعل {} بينما ( i == صحيح );forحلقة
تتكون الحلقة forمن ثلاثة أجزاء: التصريح ، والشرط ، وتعبير العداد . جميعها اختيارية.
for ( int i = 0 ; i < 10 ; i ++ ) { ... }يكافئ هذا الكود المُمثل بعبارة while، باستثناء أن المتغير هنا iليس محليًا للحلقة.
int i = 0 ; while ( i < 10 ) { //... i ++ ; }foreachحلقة
foreachيتم اشتقاق هذا البيان من forالبيان ويستخدم نمطًا معينًا موصوفًا في مواصفات لغة C# من أجل الحصول على مُعدِّد للعناصر واستخدامه للتكرار عليه.
يتم إرجاع كل عنصر في المجموعة المحددة ضمن سياق كتلة التعليمات البرمجية. عند تنفيذ الكتلة، يتم إرجاع العنصر التالي حتى لا يتبقى أي عناصر.
foreach ( int i in intList ) { ... }عبارات الانتقال
تُورَث عبارات القفز من لغات C/C++، ومن ثم من لغات التجميع. وهي تمثل تعليمات القفز في لغة التجميع التي تتحكم في تدفق البرنامج.
الملصقات gotoوالبيانات
تُعطى التسميات كنقاط في الكود يمكن الانتقال إليها باستخدام gotoالعبارة.
ابدأ : ....... اذهب إلى البداية ؛لاحظ أنه ليس من الضروري وضع التسمية بعد gotoالعبارة؛ فقد تكون قبلها في ملف المصدر.
gotoيمكن استخدام هذه العبارة في switchعبارات للانتقال من حالة إلى أخرى أو للتراجع من حالة إلى أخرى.
switch ( n ) { case 1 : Console.WriteLine ( "Case 1" ) ; break ; case 2 : Console.WriteLine ( " Case 2 " ); goto case 1 ; case 3 : Console.WriteLine ( " Case 3" ) ; case 4 : // سيفشل التجميع هنا لأن الحالات لا يمكنها الانتقال إلى الحالة التالية في C#. Console.WriteLine ( " Case 4" ); goto default ; // هذه هي الطريقة الصحيحة للانتقال إلى الحالة التالية. case 5 : // يُسمح باستخدام تسميات متعددة لنفس الكود . case 6 : default : Console.WriteLine ( "Default" ); break ; // حتى default يجب ألا يصل إلى نقطة النهاية . }breakإفادة
breakيخرج هذا الأمر من أقرب حلقة أو switchأمر. ويستمر التنفيذ في الأمر الذي يلي الأمر الذي تم إنهاؤه، إن وجد.
int e = 10 ; for ( int i = 0 ; i < e ; i ++ ) { while ( true ) { break ; } // سيتم الخروج من الحلقة عند هذه النقطة. }continueإفادة
يوقف هذا continueالبيان التكرار الحالي لعبارة التحكم الحالية ويبدأ التكرار التالي.
int ch ; while (( ch = Console . Read ()) != - 1 ) { if ( ch == ' ' ) { continue ; // يتخطى باقي حلقة while }// باقي حلقة while ... }تقوم الحلقة whileفي الكود أعلاه بقراءة الأحرف عن طريق استدعاء ، وتتخطى العبارات الموجودة في جسم الحلقة إذا كانت الأحرف مسافات.GetChar()
معالجة الاستثناءات
يتم توريث طريقة معالجة الاستثناءات في وقت التشغيل في لغة C# من لغتي Java و C++.
تحتوي مكتبة الفئات الأساسية على فئة تُسمى تُشتق منها جميع فئات الاستثناءات الأخرى. يحتوي كائن الاستثناء على جميع المعلومات المتعلقة باستثناء معين، بالإضافة إلى الاستثناءات الداخلية التي تسبب فيه. يمكن للمبرمجين تعريف استثناءاتهم الخاصة عن طريق الاشتقاق من هذه الفئة.System.ExceptionExceptionException
يمكن طرح استثناء بهذه الطريقة:
ألقِ استثناءً جديدًا من نوع NotImplementedException ();try...catch...finallyالبيانات
تتم إدارة الاستثناءات داخل الكتل.try...catch
حاول { // عبارات قد تُطلق استثناءات ... } أمسك ( استثناء ex ) { // تم التقاط الاستثناء ومعالجته هنا ... } أخيرًا { // يتم تنفيذ العبارات دائمًا بعد كتل try/catch ... }تُنفَّذ التعليمات البرمجية داخل tryالكتلة، وإذا أدى أي منها إلى ظهور استثناء، يتوقف تنفيذ الكتلة وتتولى catchالكتلة معالجة الاستثناء. قد توجد عدة catchكتل، وفي هذه الحالة تُنفَّذ أول كتلة تحتوي على متغير استثناء يتطابق نوعه مع نوع الاستثناء الذي ظهر.
إذا لم يتطابق أي جزء من التعليمات البرمجية مع نوع الاستثناء المُثار، يتوقف catchتنفيذ الجزء الخارجي (أو الدالة) الذي يحتوي على العبارة ، ويُمرر الاستثناء إلى خارج الجزء أو الدالة المُحتوية. ينتشر الاستثناء تصاعديًا عبر مكدس الاستدعاءات حتى يتم العثور على جزء مطابق داخل إحدى الدوال النشطة حاليًا. إذا انتشر الاستثناء حتى وصل إلى أعلى دالة دون العثور على جزء مطابق، يُنهى البرنامج بالكامل، ويُكتب وصف نصي للاستثناء إلى دفق الإخراج القياسي.try ... catchcatchMain()catch
finallyيتم تنفيذ العبارات الموجودة داخل الكتلة دائمًا بعد كتلتي tryو catch، سواء تم طرح استثناء أم لا.
يجب أن يتبع الكتلة إما catchكتلة واحدة، أو finallyكتلة واحدة، أو كليهما try.
الأنواع
لغة C# هي لغة ذات كتابة ثابتة مثل لغتي C و C++. هذا يعني أن كل متغير وثابت يحصل على نوع ثابت عند تعريفه. النوعان هما أنواع القيم وأنواع المراجع .
أنواع القيم
تُخزَّن نسخ أنواع القيم في مكدس الذاكرة، أي أنها مرتبطة بمتغيراتها. عند تعريف متغير لنوع قيمة، يتم تخصيص الذاكرة له مباشرةً. وإذا خرج المتغير عن نطاق التعريف، يتم حذفه.
الهياكل
تُعرف البنى عادةً باسم "structs" . البنى هي أنواع قيم يُعرّفها المستخدم باستخدام الكلمة structالمفتاحية `structs`. وهي تُشبه الأصناف، لكنها أكثر ملاءمةً للأنواع الخفيفة. سيتم عرض بعض الاختلافات النحوية المهمة بين الصنف والبنية لاحقًا في هذه المقالة .
struct Foo { ... }جميع أنواع البيانات الأولية هي هياكل بيانات.
أنواع محددة مسبقًا
| الأنواع الأولية | |||||
|---|---|---|---|---|---|
| اسم النوع | ما يعادل BCL | قيمة | يتراوح | مقاس | القيمة الافتراضية |
sbyte | System.SByte | عدد صحيح | من -128 إلى +127 | 8 بت (1 بايت) | 0 |
short | System.Int16 | عدد صحيح | من -32,768 إلى +32,767 | 16 بت (2 بايت) | 0 |
int | System.Int32 | عدد صحيح | من -2,147,483,648 إلى +2,147,483,647 | 32 بت (4 بايت) | 0 |
long | System.Int64 | عدد صحيح | من -9,223,372,036,854,775,808 إلى +9,223,372,036,854,775,807 | 64 بت (8 بايت) | 0 |
byte | System.Byte | عدد صحيح غير موقع | من 0 إلى 255 | 8 بت (1 بايت) | 0 |
ushort | System.UInt16 | عدد صحيح غير موقع | من 0 إلى 65,535 | 16 بت (2 بايت) | 0 |
uint | System.UInt32 | عدد صحيح غير موقع | من 0 إلى 4,294,967,295 | 32 بت (4 بايت) | 0 |
ulong | System.UInt64 | عدد صحيح غير موقع | من 0 إلى 18,446,744,073,709,551,615 | 64 بت (8 بايت) | 0 |
decimal | System.Decimal | عدد عشري موقع | من -79,228,162,514,264,337,593,543,950,335 إلى +79,228,162,514,264,337,593,543,950,335 | 128 بت (16 بايت) | 0.0 |
float | System.Single | عدد عشري | من ±1.401298E−45 إلى ±3.402823E+38 | 32 بت (4 بايت) | 0.0 |
double | System.Double | عدد عشري | من ±4.94065645841246E−324 إلى ±1.79769313486232E+308 | 64 بت (8 بايت) | 0.0 |
bool | System.Boolean | منطقي | trueأوfalse | 8 بت (1 بايت) | false |
char | System.Char | حرف واحد من رموز يونيكود | '\u0000'خلال'\uFFFF' | 16 بت (2 بايت) | '\u0000' |
ملاحظة:string ( ) ليس بنية بيانات وليس نوعًا بدائيًا.System.String
التعدادات
الأنواع المُعَدَّة (المُعَرَّفة باستخدام enum) هي قيم مُسماة تُمثل قيمًا عددية صحيحة.
enum Season { Winter = 0 , Spring = 1 , Summer = 2 , Autumn = 3 , Fall = Autumn // يُطلق على الخريف اسم Fall في اللغة الإنجليزية الأمريكية. }يتم تهيئة متغيرات التعداد افتراضياً إلى الصفر. ويمكن إسناد القيم المسماة المحددة بواسطة نوع التعداد إليها أو تهيئتها بها.
الموسم الموسم ؛ الموسم = الموسم . الربيع ؛المتغيرات من نوع التعداد هي قيم عددية صحيحة. يُسمح بالجمع والطرح بين متغيرات من نفس النوع دون الحاجة إلى تحويل نوعي محدد، لكن الضرب والقسمة أكثر خطورة ويتطلبان تحويلاً نوعياً صريحاً. كما يلزم التحويل النوعي لتحويل متغيرات التعداد من وإلى أنواع عددية صحيحة. مع ذلك، لا يُصدر التحويل النوعي أي استثناء إذا لم تُحدد القيمة في تعريف النوع.
season = ( Season ) 2 ; // تحويل 2 إلى قيمة تعدادية من نوع Season. season = season + 1 ; // إضافة 1 إلى القيمة. season = season + season2 ; // جمع قيم متغيرين تعداديين. int value = ( int ) season ; // تحويل القيمة التعدادية إلى قيمة عددية صحيحة.season ++ ; // Season.Spring (1) يصبح Season.Summer (2). season -- ; // Season.Summer (2) يصبح Season.Spring (1).يمكن دمج القيم باستخدام عامل التشغيل OR الثنائي |.
Color myColors = Color.Green | Color.Yellow | Color.Blue ;أنواع المراجع
المتغيرات المُنشأة لأنواع المراجع هي مراجع مُدارة مُحددة النوع. عند استدعاء الدالة البانية، يُنشأ كائن في الذاكرة الديناميكية ويُسند مرجع إلى المتغير. عندما يخرج متغير من نطاق تعريف الكائن، يُقطع المرجع، وعندما لا يتبقى أي مراجع، يُصنف الكائن على أنه كائن مهمل. ثم يقوم جامع البيانات المهملة بجمعه وتدميره.
يكون المتغير المرجعي فارغًا عندما لا يشير إلى أي كائن.
المصفوفات
نوع المصفوفة هو نوع مرجعي يشير إلى مساحة تحتوي على عنصر واحد أو أكثر من نوع معين. جميع أنواع المصفوفات مشتقة من فئة أساسية مشتركة . يُشار إلى كل عنصر بواسطة فهرسه كما هو الحال في لغتي C++ و Java.System.Array
المصفوفة في لغة C# هي ما يسمى بالمصفوفة الديناميكية في لغة C++.
int [] numbers = new int [ 2 ]; numbers [ 0 ] = 2 ; numbers [ 1 ] = 5 ; int x = numbers [ 0 ];المُهيئات
توفر مُهيئات المصفوفات صيغة ملائمة لتهيئة المصفوفات.
// الصيغة المطولة int [] numbers = new int [ 5 ] { 20 , 1 , 42 , 15 , 34 }; // الصيغة المختصرة int [] numbers2 = { 20 , 1 , 42 , 15 , 34 }; // الصيغة المستنتجة var numbers3 = new [] { 20 , 1 , 42 , 15 , 34 };المصفوفات متعددة الأبعاد
يمكن أن تحتوي المصفوفات على أكثر من بُعد واحد، على سبيل المثال بُعدين لتمثيل شبكة.
int [,] numbers = new int [ 3 , 3 ]; numbers [ 1 , 2 ] = 2 ;int [,] numbers2 = new int [ 3 , 3 ] { { 2 , 3 , 2 }, { 1 , 2 , 6 }, { 2 , 4 , 5 } };انظر أيضاً
الصفوف الدراسية
الفئات هي أنواع مرجعية ذاتية الوصف يُعرّفها المستخدم. في الأساس، جميع الأنواع في إطار عمل .NET هي فئات، بما في ذلك الهياكل والتعدادات، وهي فئات مُولّدة بواسطة المُصرّف. أعضاء الفئة مرئية privateافتراضيًا، ولكن يمكن تعريفها بحيث publicتكون مرئية خارج الفئة أو protectedلأي فئة فرعية منها.
الأوتار
يمثل هذا الصنف، أو ، تسلسلًا غير قابل للتغيير من أحرف يونيكود ( ).System.Stringstringchar
العمليات التي تُنفذ على سلسلة نصية تُعيد دائمًا سلسلة نصية جديدة.
string text = "Hello World!" ; string substr = text . Substring ( 0 , 5 ); string [] parts = text . Split ( new char []{ ' ' });يمكن استخدام هذه الفئة عندما يكون المطلوب "سلسلة" قابلة للتغيير.System.StringBuilder
StringBuilder sb = new StringBuilder ( ); sb.Append ( 'H' ); sb.Append ( " el" ); sb.AppendLine ( " lo ! " ) ;واجهة المستخدم
الواجهات هي هياكل بيانات تحتوي على تعريفات للأعضاء دون تطبيقات. المتغير من نوع واجهة هو مرجع إلى نسخة من فئة تُطبّق هذه الواجهة. انظر #الواجهات .
المندوبون
توفر لغة C# مؤشرات دوال كائنية التوجه آمنة من حيث النوع في شكل مفوضين .
class Program { // نوع المندوب: delegate int Operation ( int a , int b );دالة ثابتة int Add ( int i1 , int i2 ) { return i1 + i2 ; }static int Sub ( int i1 , int i2 ) { return i1 - i2 ; }static void Main () { // إنشاء نسخة من المندوب وتعيين الدالة له. Operation op = Add ;// استدعاء الدالة التي يشير إليها المندوب. int result1 = op ( 2 , 3 ); // 5op = Sub ; int result2 = op ( 10 , 2 ); // 8 } }تهيئة المندوب باستخدام طريقة مجهولة.
الجمع = المندوب ( int a , int b ) { إرجاع a + b ; };تهيئة المندوب باستخدام تعبير لامدا.
الجمع = ( أ ، ب ) => أ + ب ؛الفعاليات
الأحداث عبارة عن مؤشرات يمكنها الإشارة إلى عدة دوال. وبشكل أدق، فهي تربط مؤشرات الدوال بمعرف واحد. لذا، يمكن اعتبارها امتدادًا للمفوضين . وتُستخدم عادةً كمحفزات في تطوير واجهات المستخدم. يعتمد الشكل المستخدم في لغة C# وبقية بنية اللغة المشتركة على لغة Visual Basic الكلاسيكية .
باستخدام System.Windows.Controls ؛delegate void MouseEventHandler ( object sender , MouseEventArgs e );public class Button : Control { private event MouseEventHandler _onClick ;/* دالة تشغيل افتراضية */ void Click () { _onClick ( this , new MouseEventArgs ( data )); } }يتطلب الحدث معالج أحداث مصاحبًا ، يتم إنشاؤه من خلال مندوب خاص، والذي عادةً ما يأخذ في مكتبات خاصة بالمنصة، مثل Windows Presentation Foundation و Windows Forms، معلَمين: وسيطات المُرسِل ووسيطات الحدث . ويُستمد نوع كائن وسيطات الحدث من فئة EventArgs، وهي جزء من مكتبة CLI الأساسية.
بمجرد تعريف الحدث في فئته، فإن الطريقة الوحيدة لاستدعائه هي من داخل الكائن المالك. يمكن تنفيذ دالة استماع خارجية ليتم تشغيلها عند وقوع الحدث.
public class MainWindow : System.Windows.Controls.Window { private Button _button1 ;public MainWindow () { _button1 = new Button (); _button1 . Text = "انقر هنا!" ;/* الاشتراك في الحدث */ _button1 . ClickEvent += Button1_OnClick ;/* صيغة بديلة تُعتبر قديمة: _button1.MouseClick += new MouseEventHandler(Button1_OnClick); */ }protected void Button1_OnClick ( object sender , MouseEventArgs e ) { MessageBox . Show ( "تم النقر!" ); } }كما يمكن تنفيذ الأحداث المخصصة:
private EventHandler _clickHandles = ( s , e ) => { };public event EventHandler Click { add { // بعض التعليمات البرمجية التي يتم تشغيلها عند إضافة المعالج... ..._clickHandles += value ; } remove { // بعض التعليمات البرمجية التي يتم تشغيلها عند إزالة المعالج... ..._clickHandles -= value ; } }انظر أيضاً
أنواع قابلة للتصفير
- هذه ميزة من ميزات لغة C# 2.0 .
تم تقديم أنواع القيم القابلة للتصفير في C# 2.0 أولاً لتمكين أنواع القيم من أن تكون فارغة (مفيد عند العمل مع قاعدة بيانات).
int? n = 2 ; n = null ;Console.WriteLine ( n.HasValue ) ;هذا يشبه استخدام البنية.Nullable<T>
Nullable <int> n = 2 ; n = null ;Console.WriteLine ( n.HasValue ) ;نصائح
تدعم لغة C# المؤشرات إلى أنواع محددة (بعض الأنواع الأولية، والتعدادات، والسلاسل النصية، والمؤشرات، وحتى المصفوفات والهياكل إذا كانت تحتوي فقط على أنواع يمكن الإشارة إليها [ 14 ] ) في سياق غير آمن: الدوال وكتل التعليمات البرمجية المميزة بعلامة `<input> unsafe`. وهي متطابقة نحويًا مع المؤشرات في لغتي C وC++. مع ذلك، يتم تعطيل التحقق أثناء التشغيل داخل unsafeالكتل.
static void Main ( string [] args ) { unsafe { int a = 2 ; int * b = &a a ؛Console.WriteLine ( " عنوان a: {0}. القيمة: {1}" , ( int ) & a a ، أ ); Console . WriteLine ( "عنوان b: {0}. القيمة: {1}. قيمة *b: {2}" , ( int ) & b , ( int ) b , * b );// سيُخرج شيئًا مثل: // عنوان a: 71953600. القيمة: 2 // عنوان b: 71953596. القيمة: 71953600. قيمة *b: 2 } }لا يُشترط أن تكون الهياكل هياكل خالصة بدون أعضاء من نوع مرجعي مُدار، على سبيل المثال سلسلة نصية أو أي فئة أخرى.
public struct MyStruct { public char Character ; public int Integer ; }public struct MyContainerStruct { public byte Byte ; public MyStruct MyStruct ; }قيد الاستخدام:
MyContainerStruct x ; MyContainerStruct * ptr = & x ;قيمة البايت = ptr -> بايت ؛متحرك
- هذه ميزة من ميزات C# 4.0 و .NET Framework 4.0 .
يُمكّن النوع dynamicمن البحث الديناميكي في وقت التشغيل عن لغة C# بطريقة ثابتة. يشير مصطلح "ديناميكي" إلى متغير يحتوي على كائن بنوع يتم تحديده في وقت التشغيل، وليس في وقت الترجمة.
تستفيد هذه الميزة من وقت تشغيل اللغة الديناميكية (DLR) وهي مصممة بهدف التشغيل البيني مع اللغات ذات الكتابة الديناميكية مثل IronPython و IronRuby (تطبيقات Python و Ruby لـ .NET).
كما أن الدعم الديناميكي يسهل التفاعل مع كائنات COM .
dynamic x = new Foo (); x.DoSomething ( ); // سيتم تجميع الكود وحله أثناء التشغيل. سيتم طرح استثناء في حالة عدم الصلاحية.الأنواع المجهولة
- هذه ميزة من ميزات لغة C# 3.0 .
الأنواع المجهولة هي فئات بلا أسماء يُنشئها المُصرّف. وهي قابلة للاستخدام فقط، ومع ذلك فهي مفيدة في سيناريوهات مثل استعلام LINQ الذي يُعيد كائنًا، أو selectلإعادة قيم مُحددة. بعد ذلك، عرّف نوعًا مجهولًا يحتوي على حقول للقراءة فقط مُنشأة تلقائيًا لهذه القيم.
عند إنشاء تعريف نوع مجهول آخر بنفس التوقيع، يتم استنتاج النوع تلقائيًا بواسطة المترجم.
var carl = new { Name = "Carl" , Age = 35 }; // اسم النوع معروف للمترجم فقط. var mary = new { Name = "Mary" , Age = 22 }; // نفس نوع التعبير أعلاهالتعبئة وفتح الصناديق
التغليف هو عملية تحويل قيمة من نوع قيمة إلى قيمة من نوع مرجعي مطابق. [ 15 ] التغليف في لغة C# ضمني.
عملية فك التغليف هي عملية تحويل قيمة من نوع مرجعي (تم تغليفها مسبقًا) إلى قيمة من نوع قيمة. [ 15 ] تتطلب عملية فك التغليف في لغة C# تحويلًا صريحًا للنوع.
مثال:
int foo = 42 ; // نوع القيمة. object bar = foo ; // تم تحويل foo إلى bar. int foo2 = ( int ) bar ; // تم فك تحويله إلى نوع القيمة.البرمجة الكائنية التوجه
تدعم لغة C# البرمجة الكائنية التوجه بشكل مباشر .
أشياء
يتم إنشاء كائن باستخدام النوع كقالب ويسمى مثيلًا لهذا النوع المحدد.
في لغة C#، تكون الكائنات إما مراجع أو قيم. ولا يوجد تمييز نحوي بينهما في الكود.
فئة الكائن
جميع الأنواع، حتى أنواع القيم في شكلها المُغلّف، ترث ضمنيًا من الفئة الأساسية. تحتوي هذه الفئة على أكثر الطرق شيوعًا التي تشترك فيها جميع الكائنات. بعض هذه الطرق مُعرّفة ويمكن إعادة تعريفها.System.Objectvirtual
ترث الفئات إما بشكل مباشر أو غير مباشر من خلال فئة أساسية أخرى.System.Object
بعض أعضاء فئة الكائن:
Equals- يدعم المقارنات بين الكائنات.Finalize- يقوم بعمليات التنظيف قبل استعادة الكائن تلقائيًا. (المدمر الافتراضي)GetHashCode- يحصل على الرقم المقابل لقيمة الكائن لدعم استخدام جدول التجزئة .GetType- يحصل على نوع المثيل الحالي.ToString- يُنشئ سلسلة نصية قابلة للقراءة البشرية تصف مثيلًا من الفئة. وعادةً ما يُعيد اسم النوع.
الصفوف الدراسية
تُعدّ الفئات من أساسيات لغة البرمجة الكائنية مثل C#. فهي بمثابة قالب للكائنات، وتحتوي على عناصر تخزن البيانات وتتعامل معها بطريقة تحاكي الواقع.
الاختلافات بين الفئات والهياكل
على الرغم من تشابه الأصناف والهياكل في طريقة تعريفها واستخدامها، إلا أن هناك اختلافات جوهرية بينهما. فالأصناف هي أنواع مرجعية، بينما الهياكل هي أنواع قيمية. يُخصص للهيكل مساحة على المكدس عند تعريفه، ويرتبط المتغير بعنوانه، ويحتوي مباشرةً على القيمة. أما الأصناف، فتختلف لأن ذاكرتها تُخصص على الكومة. المتغيرات هي مراجع، أي مؤشرات مُدارة على المكدس تشير إلى الكائنات.
تختلف البنى عن الأصناف في جوانب أخرى. فعلى سبيل المثال، بينما يوفر كلاهما مُنشئًا افتراضيًا ضمنيًا لا يأخذ أي وسيط، لا يمكن إعادة تعريفه في البنى. يؤدي تعريف مُنشئ ذي معلمات مختلفة بشكل صريح إلى تجاوز المُنشئ الافتراضي الضمني في الأصناف، ولكن ليس في البنى. يجب تهيئة جميع حقول البنية في تلك المُنشئات. لا تحتوي البنى على مُنهيات ولا يمكنها الوراثة من صنف آخر كما تفعل الأصناف. ضمنيًا، هي مُغلقة وترث من (التي ترث من ). تُعد البنى أكثر ملاءمة لكميات البيانات الصغيرة.System.ValueTypeSystem.Object
| المُنشئ الافتراضي | المُنهي | تهيئة الأعضاء | الميراث | |
|---|---|---|---|---|
| الصفوف الدراسية | غير مطلوب (تم إنشاؤه تلقائيًا) [ أ ] | نعم | غير مطلوب | نعم (إذا لم تكن الفئة الأساسية كذلك sealed) |
| الهياكل | مطلوب (تم إنشاؤه تلقائيًا) [ ب ] | لا | مطلوب | غير مدعوم |
تصريح
إعلان الفئة:
class Foo { // تعريفات الأعضاء }فئة جزئية
- هذه ميزة من ميزات لغة C# 2.0 .
الفئة الجزئية هي تعريف فئة يُقسّم رمزها إلى ملفات منفصلة. يجب تمييز الأجزاء المختلفة من الفئة الجزئية بالكلمة المفتاحية partial.
// File1.cs partial class Foo { ... }// File2.cs partial class Foo { ... }السبب المعتاد لاستخدام الفئات الجزئية هو تقسيم فئة ما إلى أجزاء يتم صيانتها بواسطة المبرمج وأجزاء يتم صيانتها بواسطة الأداة، أي يتم إنشاء بعض التعليمات البرمجية تلقائيًا بواسطة أداة تصميم واجهة المستخدم أو شيء مشابه.
التهيئة
قبل استخدام عناصر الفئة، يجب تهيئة المتغير بمرجع إلى كائن. لإنشائه، استدعِ المُنشئ المناسب باستخدام الكلمة newالمفتاحية. يحمل المتغير نفس اسم الفئة.
Foo foo = new Foo (); StreamReader sr = new StreamReader ( "MyFile.txt" );بالنسبة للهياكل، يُعد استدعاء الدالة البانية بشكل صريح اختيارياً، لأن الدالة البانية الافتراضية تُستدعى تلقائياً. يجب تعريفها، ويتم تهيئتها بقيم قياسية.
لتقليل التعليمات البرمجية المتكررة، إذا تم تحديد النوع في إعلان (أي عدم استخدام var)، فيمكن استدعاء المُنشئ باستخدام فقط new().
Foo foo = new (); StreamReader sr = new ( "MyFile.txt" );مُهيئات الكائنات
- هذه ميزة من ميزات لغة C# 3.0 .
يُوفر هذا طريقةً أكثر ملاءمةً لتهيئة الحقول والخصائص العامة للكائن. استدعاءات المُنشئ اختيارية في حال وجود مُنشئ افتراضي.
Person person = new Person { Name = "John Doe" , Age = 39 };// يساوي Person person = new Person (); person.Name = " John Doe " ; person.Age = 39 ;مُهيئات المجموعة
- هذه ميزة من ميزات لغة C# 3.0 .
تُوفّر مُهيئات المجموعات صيغةً شبيهةً بالمصفوفات لتهيئة المجموعات. يُولّد المُصرّف استدعاءاتٍ للدالة Add. هذا يعمل مع الفئات التي تُطبّق الواجهة ICollection.
List <int> list = new List <int> { 2 , 5 , 6 , 6 } ;// يساوي List <int> list = new List <int> ( ) ; list.Add ( 2 ) ; list.Add ( 5 ) ; list.Add ( 6 ) ; list.Add ( 6 ) ;الوصول إلى الأعضاء
يتم الوصول إلى أعضاء مثيل وأعضاء ثابتة من فئة باستخدام .عامل التشغيل.
الوصول إلى عضو من أعضاء المثيل: يمكن الوصول إلى أعضاء المثيل من خلال اسم متغير.
string foo = "Hello" ; string fooUpper = foo . ToUpper ();الوصول إلى عضو ثابت في الفئة: يتم الوصول إلى الأعضاء الثابتة باستخدام اسم الفئة أو نوع آخر.
int r = String.Compare ( foo , fooUpper ) ;الوصول إلى عضو من خلال مؤشر في التعليمات البرمجية غير الآمنة ، يتم الوصول إلى أعضاء القيمة (نوع البنية) المشار إليها بواسطة مؤشر باستخدام ->المعامل كما هو الحال في لغتي C و C++.
النقطة p ؛ p.X = 2 ؛ p.Y = 6 ؛ النقطة * ptr = & p ؛ ptr- > Y = 4 ؛المُعدِّلات
المُعدِّلات هي كلمات مفتاحية تُستخدم لتعديل تعريفات الأنواع وأعضاء الأنواع. وأبرزها مجموعة فرعية تحتوي على مُعدِّلات الوصول.
مُعدِّلات الفئة
abstract- يحدد هذا الخيار أن الصنف يُستخدم فقط كصنف أساسي، ويتم تنفيذه في صنف موروث. وهو شرط أساسي لاحتواء الأصناف على توابع مجردة.sealed- يحدد أنه لا يمكن توريث فئة معينة.
مُعدِّلات أعضاء الفئة
abstract- يعلن عن وجود طريقة متاحة في جميع الفئات المشتقة غير المجردة.const- يحدد أن المتغير عبارة عن قيمة ثابتة يجب تهيئتها عند تعريفها.event- يعلن عن حدث ما.extern- يحدد أن توقيع الأسلوب بدون جسم يستخدم استيراد DLL .override- يحدد أن تعريف الطريقة أو الخاصية هو تجاوز لعضو افتراضي أو تنفيذ لعضو من فئة مجردة.readonly- يعلن عن حقل لا يمكن تعيين قيم له إلا كجزء من الإعلان أو في دالة البناء في نفس الفئة.unsafe- يحدد سياقًا غير آمن، مما يسمح باستخدام المؤشرات.virtual- يحدد أنه يمكن تجاوز تعريف طريقة أو خاصية بواسطة فئة مشتقة.volatile- يحدد حقلاً يمكن تعديله بواسطة عملية خارجية ويمنع المترجم المحسن من التخمين بشأن استمرار القيمة الحالية للحقل.
staticمعدل
يشير المُعدِّل staticإلى أن العضو ينتمي إلى الصنف وليس إلى كائن مُحدد. يُسمح للأصناف المُعَلَّمة بـ "static" فقط باحتواء أعضاء ثابتة. يُشار أحيانًا إلى الأعضاء الثابتة بأعضاء الصنف لأنها تنطبق على الصنف ككل وليس على مثيلاته.
public class Foo { public static void Something () { ... } } // استدعاء دالة الفئة. Foo . Something ();مُعدِّلات الوصول
تُحدد مُعدِّلات الوصول ، أو مُعدِّلات الوراثة ، إمكانية الوصول إلى الفئات والأساليب والأعضاء الأخرى. publicيمكن الوصول إلى العناصر المُعَلَّمة من أي مكان. privateلا يمكن الوصول إلى الأعضاء إلا من الفئة التي تم تعريفها فيها، وتكون مخفية عند الوراثة. الأعضاء التي تحمل protectedالمُعدِّل تكون مخفية private، ولكن يمكن الوصول إليها عند الوراثة. internalلا يمكن الوصول إلى الفئات والأعضاء إلا من داخل التجميع المُعَرِّف.
تكون الفئات والهياكل ضمنية internal، وكذلك الأعضاء، privateإذا لم يكن لديهم مُعدِّل وصول.
public class Foo { public int Do () { return 0 ; }public class Bar {} }| الأنواع غير المتداخلة | الأعضاء (بما في ذلك الأنواع المتداخلة) | متاح لـ | |
|---|---|---|---|
public | نعم | نعم | الجميع |
protected internal | لا | نعم | نفس الفئة، والفئات المشتقة، وكل شيء في نفس التجميعة |
protected | لا | نعم | نفس الفئة والفئات المشتقة |
internal | نعم (افتراضي) | نعم | كل شيء في نفس التجميع |
private protected | لا | نعم | نفس الفئة، والفئات المشتقة في نفس التجميع |
private | لا | نعم (افتراضي) | نفس الصفوف |
المُنشئون
المُنشئ هو دالة خاصة تُستدعى عند إنشاء كائن. وظيفته تهيئة خصائص الكائن. تحمل المُنشئات نفس اسم الصنف، ولا تُرجع أي قيمة. تُرجع ضمنيًا الكائن المُنشأ حديثًا عند استدعائها باستخدام المعامل new. قد تأخذ المُنشئات معاملات كأي دالة أخرى. المُنشئ بدون معاملات مميز لأنه يُمكن تحديده كشرط ضروري لمعامل نوع عام.
class Foo { Foo () { ... } }يمكن أن تكون المُنشئاتpublic ، أو private، protectedأو internal.
المدمر
يتم استدعاء دالة التدمير عندما يقوم جامع البيانات المهملة بجمع الكائن لإجراء عملية تنظيف يدوية. finalizeويمكن تجاوز دالة التدمير الافتراضية.
يشبه تركيبها تركيب الدوال البانية. الفرق هو أن الاسم يسبقه رمز "~" ولا يمكن أن يتضمن معاملات. لا يمكن تعريف سوى دالة تدمير واحدة.
class Foo { ...~ Foo () { ... } }المُنهيات دائمًا ما تكون private.
طُرق
كما هو الحال في لغتي C و C++، تُجمّع الدوال الشيفرة القابلة لإعادة الاستخدام. والفرق الرئيسي هو أن الدوال، كما في لغة Java، يجب أن تكون موجودة داخل فئة. ولذلك تُسمى الدالة " طريقة" . للطريقة قيمة مُعادة، واسم، وعادةً ما تحتوي على مُعاملات يتم تهيئتها عند استدعائها. ويمكن أن تنتمي إما إلى نسخة من فئة أو أن تكون ثابتة.
class Foo { int Bar ( int a , int b ) { return a % b ; } }يتم استدعاء الطريقة باستخدام الترميز على متغير معين ،. أو كما هو الحال في الطرق الثابتة، اسم نوع.
Foo foo = new Foo ( ); int r = foo.Bar ( 7 , 2 ) ;Console.WriteLine ( r ) ;refوالمعاييرout
تُمرَّر الوسائط بالمرجع عند استدعاء دالة بمعاملات مسبوقة بالكلمات المفتاحية `_` refأو ` out_`. تُفيد هذه المؤشرات المُدارة عند تمرير متغيرات لتعديلها داخل الدالة. الفرق الرئيسي بينهما هو أنه outيجب تعيين قيمة للمعامل داخل الدالة قبل انتهاء الدالة. refقد تُعيِّن `_` قيمة جديدة أو لا، ولكن يجب تهيئة متغير المعامل قبل استدعاء الدالة.
void PassRef ( ref int x ) { if ( x == 2 ) { x = 10 ; } } int Z = 7 ; PassRef ( ref Z );void PassOut ( out int x ) { x = 2 ; } int Q ; PassOut ( out Q );المعلمات الاختيارية
- هذه ميزة من ميزات لغة C# 4.0 .
يُقدّم الإصدار 4.0 من لغة C# معلمات اختيارية بقيم افتراضية كما هو الحال في لغة C++. على سبيل المثال:
void Increment ( ref int x , int dx = 1 ) { x += dx ; }int x = 0 ; Increment ( ref x ); // يأخذ dx القيمة الافتراضية 1 Increment ( ref x , 2 ); // يأخذ dx القيمة 2بالإضافة إلى ذلك، ولتكملة المعاملات الاختيارية، يُمكن تحديد أسماء المعاملات صراحةً في استدعاءات الدوال، وذلك لتمرير مجموعة فرعية من المعاملات الاختيارية لدالة معينة. الشرط الوحيد هو وضع المعاملات المُسماة بعد المعاملات غير المُسماة. يُمكن تحديد أسماء المعاملات لكلٍ من المعاملات الاختيارية والإلزامية، ويُمكن استخدامها لتحسين قابلية القراءة أو إعادة ترتيب الوسائط في الاستدعاء. على سبيل المثال:
Stream OpenFile ( string name , FileMode mode = FileMode . Open , FileAccess access = FileAccess . Read ) { ... }OpenFile ( "file.txt" ); // استخدم القيم الافتراضية لكل من "mode" و"access" OpenFile ( " file.txt" , mode : FileMode.Create ) ; // استخدم القيمة الافتراضية لـ "access" OpenFile ( " file.txt" , access : FileAccess.Read ) ; // استخدم القيمة الافتراضية لـ "mode" OpenFile ( name : "file.txt" , access : FileAccess.Read , mode : FileMode.Create ) ; // قم بتسمية جميع المعاملات لزيادة سهولة القراءة، // واستخدم ترتيبًا مختلفًا عن ترتيب تعريف الدالةتُسهّل المعاملات الاختيارية التفاعل مع COM. سابقًا، كان على لغة C# تمرير جميع المعاملات في دالة مكون COM، حتى تلك الاختيارية. على سبيل المثال:
object fileName = "Test.docx" ; object missing = System . Reflection . Missing . Value ;doc.SaveAs ( ref fileName , ref missing , ref missing , ref missing , ref missing , ref missing , ref missing , ref missing , ref missing , ref missing , ref missing , ref missing , ref missing , ref missing , ref missing , ref missing ) ; console.writeline ( " تم حفظ الملف بنجاح" );بفضل دعم المعاملات الاختيارية، يمكن اختصار الكود إلى
doc.SaveAs ( ref fileName ) ;extern
يمكن للغة C# استدعاء التعليمات البرمجية الأصلية. يتم تعريف توقيع الدالة بدون جسم ويتم تمييزه بـ extern. DllImportتشير السمة إلى مكتبة الارتباط الديناميكي (DLL) المطلوبة.
[DllImport("win32.dll")] static extern double Pow ( double a , double b );الحقول
يمكن تعريف الحقول، أو متغيرات النسخة ، داخل جسم الفئة لتخزين البيانات.
class Foo { double foo ; }يمكن تهيئة الحقول مباشرة عند تعريفها (إلا إذا تم تعريفها في بنية).
class Foo { double foo = 2.3 ; }مُعدِّلات الحقول:
const- يجعل المجال ثابتًا.private- يجعل الحقل خاصًا (افتراضيًا).protected- يجعل الملعب محميًا.public- يجعل المجال عامًا.readonly- يسمح بتهيئة الحقل مرة واحدة فقط في الدالة البانية.static- يجعل الحقل عضوًا ثابتًا، أي متغيرًا من متغيرات الفئة .
ملكيات
تُضفي الخصائص بنيةً شبيهةً بالحقول وتجمعها مع الطرق. يمكن أن تحتوي الخاصية على طريقتين للوصول: getو set.
public class Person { private string _name ;string Name { get { return _name ; } set { _name = value ; } } }// استخدام خاصية var person = new Person ( ); person.Name = " Robert" ;مُعدِّلات الخصائص:
private- يجعل الخاصية خاصة (افتراضياً).protected- يجعل الممتلكات محمية.public- يجعل العقار عامًا.static- يجعل الخاصية عضوًا ثابتًا.
مُعدِّلات الوصول إلى الخصائص:
private- يجعل الوصول خاصًا.protected- يجعل جهاز الوصول محميًا.public- يجعل الوصول عامًا.
تُورَث المُعدِّلات الافتراضية لوظائف الوصول من الخاصية. لاحظ أن مُعدِّلات وظيفة الوصول لا يمكن أن تكون إلا مساوية أو أكثر تقييدًا من مُعدِّل الخاصية.
الخصائص التلقائية
- هذه ميزة من ميزات لغة C# 3.0 .
تستخدم الخصائص المنفذة تلقائيًا أدوات الوصول بدون أجسام بحيث يقوم المترجم بإنشاء حقل داعم والتعليمات البرمجية اللازمة.
public double Width { get ; private set ; }الفهرسة
تُضيف الفهارس إمكانيات فهرسة شبيهة بالمصفوفات إلى الكائنات. ويتم تنفيذها بطريقة مشابهة للخصائص.
فئة داخلية IntList { مصفوفة أعداد صحيحة خاصة _items ;int this [ int index ] { get { return _items [ index ]; } set { _items [ index ] = value ; } } }// باستخدام مُفهرس IntList list = new IntList (); list [ 2 ] = 2 ;الميراث
في لغة C#، لا يمكن للفئات أن ترث إلا من فئة واحدة. يمكن للفئة أن ترث من أي فئة غير مُعَلَّمة بـ sealed.
الفئة أ { }الفئة ب : أ {}virtual
توفر الطرق المميزة virtualتنفيذًا يمكن تجاوزه بواسطة الورثة باستخدام الكلمة overrideالمفتاحية.
يتم اختيار طريقة التنفيذ بناءً على نوع الكائن وليس نوع المتغير.
class Operation { public virtual int Do () { return 0 ; } }class NewOperation : Operation { public override int Do () { return 1 ; } }new
عند إعادة تعريف دالة غير افتراضية بتوقيع مختلف، newيمكن استخدام الكلمة المفتاحية. ويتم اختيار الدالة المستخدمة بناءً على نوع المتغير وليس نوع الكائن.
class Operation { public int Do () { return 0 ; } }class NewOperation : Operation { public new double Do () { return 4.0 ; } }وهذا يوضح الحالة:
NewOperation op = new NewOperation ();// سيتم استدعاء "double Do()" في NewOperation double d = op . Do ();العملية op_ = op ;// سيتم استدعاء "int Do()" في العملية int i = op_ . Do ();abstract
الفئات المجردة هي فئات تعمل كقوالب ولا يمكن تهيئتها. بخلاف ذلك، فهي تشبه الفئة العادية تمامًا.
الأعضاء المجردة هي أعضاء في فئات مجردة ليس لها تطبيق. يجب إعادة تعريفها بواسطة الفئات غير المجردة التي ترث العضو.
فئة مجردة من الثدييات { دالة عامة مجردة من نوع Walk (); }class Human : Mammal { public override void Walk () {}... }sealed
يمكن دمج هذا sealedالمعدل مع المعدلات الأخرى لجعلها غير قابلة للتوريث، أو لأساليب تمنع تجاوزها في الفئات المشتقة.
فئة داخلية مغلقة Foo { //... }public class Bar { public virtual void Action () { //... } }public class Baz : Bar { public sealed override void Action () { //... } }واجهات
الواجهات هي هياكل بيانات تحتوي على تعريفات للأعضاء، ولكن ليس على تطبيقاتها. تُستخدم لتحديد عقد بين أعضاء من أنواع مختلفة ذات تطبيقات مختلفة. يمكن توفير تعريفات للأساليب والخصائص والفهارس. أعضاء الواجهة عامة ضمنيًا. يمكن تطبيق الواجهة ضمنيًا أو صراحةً.
واجهة IBinaryOperation { double A { get ; set ; } double B { get ; set ; }double GetResult (); }تنفيذ واجهة
يتم تنفيذ الواجهة بواسطة فئة أو توسيعها بواسطة واجهة أخرى بنفس الطريقة التي يتم بها اشتقاق فئة من فئة أخرى باستخدام الترميز :.
التنفيذ الضمني
عند تطبيق واجهة ضمنيًا، يجب أن تكون عناصر الواجهة public.
public class Adder : IBinaryOperation { public double A { get ; set ; } public double B { get ; set ; }public double GetResult () { return A + B ; } }public class Multiplier : IBinaryOperation { public double A { get ; set ; } public double B { get ; set ; }public double GetResult () { return A * B ; } }قيد الاستخدام:
IBinaryOperation op = null ; double result ;// تقوم وحدة الجمع بتنفيذ الواجهة IBinaryOperation.op = new Adder ()؛ مرجع سابق . أ = 2 ; مرجع سابق . ب = 3 ;النتيجة = المرجع . الحصول على النتيجة ()؛ // 5// يقوم المضاعف أيضًا بتنفيذ الواجهة.المرجع = مضاعف جديد ()؛ مرجع سابق . أ = 5 ؛ مرجع سابق . ب = 4 ;النتيجة = المرجع . الحصول على النتيجة ()؛ // 20التنفيذ الصريح
لا يمكن الوصول إلى الأعضاء المطبقة بشكل صريح إلا عند التعامل مع الكائن كنوع واجهة.
public class Adder : IBinaryOperation { double IBinaryOperation.A { get ; set ; } double IBinaryOperation.B { get ; set ; }double IBinaryOperation.GetResult ( ) { return (( IBinaryOperation ) this ) .A + ( ( IBinaryOperation ) this ) .B ; } }قيد الاستخدام:
Adder add = new Adder ();// لا يمكن الوصول إلى هذه العناصر: // add.A = 2; // add.B = 3; // double result = add.GetResult();// تحويل النوع إلى نوع الواجهة للوصول إليها: IBinaryOperation add2 = add ; add2 . A = 2 ; add2 . B = 3 ;double result = add2 . GetResult ();يتم تنفيذ الخصائص الموجودة في الفئة التي تمتد IBinaryOperationتلقائيًا بواسطة المترجم ويتم إضافة حقل داعم تلقائيًا (انظر #الخصائص التلقائية ).
توسيع واجهات متعددة
يُسمح للواجهات والفئات بتوسيع واجهات متعددة.
class MyClass : IInterfaceA , IInterfaceB { ... }واجهة تمتد من واجهتين.
interface IInterfaceC : IInterfaceA , IInterfaceB { ... }الواجهات مقابل الفئات المجردة
تتشابه الواجهات والفئات المجردة. فيما يلي وصف لبعض الاختلافات المهمة:
- قد تحتوي الفئة المجردة على متغيرات أعضاء بالإضافة إلى طرق أو خصائص غير مجردة. أما الواجهة فلا يمكنها ذلك.
- لا يمكن للفئة أو الفئة المجردة أن ترث إلا من فئة أو فئة مجردة واحدة.
- قد يقوم الصنف أو الصنف المجرد بتنفيذ واجهة واحدة أو أكثر.
- لا يمكن للواجهة أن تمتد إلا إلى واجهات أخرى.
- قد تحتوي الفئة المجردة على أساليب وخصائص غير عامة (حتى وإن كانت مجردة). أما الواجهة فلا يمكن أن تحتوي إلا على أعضاء عامة.
- قد تحتوي الفئة المجردة على ثوابت، وطرق ثابتة، وأعضاء ثابتة. أما الواجهة فلا يمكنها ذلك.
- قد تحتوي الفئة المجردة على دوال إنشاء. أما الواجهة فلا يمكن أن تحتوي عليها.
الأدوية الجنيسة
- هذه ميزة من ميزات C# 2.0 و .NET Framework 2.0 .
تستخدم الأنواع العامة (أو الأنواع المُعَلمة، أو تعدد الأشكال المُعَلم ) مُعَلمات النوع، مما يُتيح تصميم فئات وأساليب لا تُحدد النوع المُستخدم إلا عند إنشاء مثيل للفئة أو الأسلوب. وتتمثل الميزة الرئيسية في إمكانية استخدام مُعَلمات النوع العامة لإنشاء فئات وأساليب يُمكن استخدامها دون تكبّد تكلفة عمليات التحويل أو التغليف في وقت التشغيل، كما في: [ 16 ]
// تعريف الفئة العامة.public class GenericList <T> { void Add ( T input ) { } }class TestGenericList { private class ExampleClass { } static void Main () { // تعريف قائمة من النوع int. GenericList < int > list1 = new GenericList < int > ();// تعريف قائمة من نوع سلسلة نصية . GenericList <string> list2 = new GenericList <string> ( ) ;// تعريف قائمة من النوع ExampleClass . GenericList <ExampleClass> list3 = new GenericList <ExampleClass> ( ) ; } }بالمقارنة مع قوالب C++ ، توفر الأنواع العامة في C# مستوى أمان أعلى، ولكنها محدودة الإمكانيات نوعًا ما. [ 17 ] على سبيل المثال، لا يمكن استدعاء عوامل التشغيل الحسابية على نوع عام في C#. [ 18 ] على عكس قوالب C++، تُنشأ الأنواع المُعاملة في .NET أثناء وقت التشغيل وليس بواسطة المُصرّف؛ لذا فهي تدعم لغات برمجة متعددة، بينما لا تدعمها قوالب C++. كما أنها تدعم بعض الميزات غير المدعومة مباشرةً في قوالب C++، مثل قيود النوع على المعاملات العامة باستخدام الواجهات. من ناحية أخرى، لا تدعم C# المعاملات العامة غير النوعية.
على عكس الأنواع العامة في جافا، تستخدم الأنواع العامة في .NET التجسيد لجعل الأنواع ذات المعاملات كائنات من الدرجة الأولى في الآلة الافتراضية للبنية التحتية للغة المشتركة (CLI) ، مما يسمح بتحسينات وحفظ معلومات النوع. [ 19 ]
استخدام الأدوية العامة
الفئات العامة
يمكن أن تكون الفئات والهياكل عامة.
public class List <T> { ... public void Add ( T item ) { ... } }var list = new List <int> ( ) ; list.Add ( 6 ) ; list.Add ( 2 ) ;واجهات عامة
interface IEnumerable <T> { ... }المندوبون العامون
delegate R Func < T1 , T2 , R > ( T1 a1 , T2 a2 );الأساليب العامة
public static T [ ] CombineArrays <T> ( T [ ] a , T [ ] b ) { T [ ] newArray = new T [ a.Length + b.Length ] ; a.CopyTo ( newArray , 0 ) ; b.CopyTo ( newArray , a.Length ) ; return newArray ; }string[]a=newstring[]{"a","b","c"};string[]b=newstring[]{"1","2","3"};string[]c=CombineArrays(a,b);double[]da=newdouble[]{1.2,2.17,3.141592};double[]db=newdouble[]{4.44,5.6,6.02};double[]dc=CombineArrays(da,db);// c is a string array containing { "a", "b", "c", "1", "2", "3"}// dc is a double array containing { 1.2, 2.17, 3.141592, 4.44, 5.6, 6.02}Type-parameters
Type-parameters are names used in place of concrete types when defining a new generic. They may be associated with classes or methods by placing the type parameter in angle brackets <>. When instantiating (or calling) a generic, one can then substitute a concrete type for the type-parameter one gave in its declaration. Type parameters may be constrained by use of the where keyword and a constraint specification, any of the six comma separated constraints may be used:[20]
| Constraint | Explanation |
|---|---|
whereT:struct | type parameter must be a value type |
whereT:class | type parameter must be a reference type |
whereT:new() | type parameter must have a constructor with no parameters (must appear last) |
whereT:<base_class> | type parameter must inherit from <base_class> |
whereT:<interface> | type parameter must be, or must implement this interface |
whereT:U | naked type parameter constraint |
Covariance and contravariance
- This is a feature of C# 4.0 and .NET Framework 4.0.
Generic interfaces and delegates can have their type parameters marked as covariant or contravariant, using keywords out and in, respectively. These declarations are then respected for type conversions, both implicit and explicit, and both compile-time and run-time. For example, the existing interface IEnumerable<T> has been redefined as follows:
interfaceIEnumerable<outT>{IEnumerator<T>GetEnumerator();}Therefore, any class that implements IEnumerable<Derived> for some class Derived is also considered to be compatible with IEnumerable<Base> for all classes and interfaces Base that Derived extends, directly, or indirectly. In practice, it makes it possible to write code such as:
voidPrintAll(IEnumerable<object>objects){foreach(objectoinobjects){System.Console.WriteLine(o);}}IEnumerable<string>strings=newList<string>();PrintAll(strings);// IEnumerable<string> is implicitly converted to IEnumerable<object>For contravariance, the existing interface IComparer<T> has been redefined as:
publicinterfaceIComparer<inT>{intCompare(Tx,Ty);}Therefore, any class that implements IComparer<Base> for some class Base is also considered to be compatible with IComparer<Derived> for all classes and interfaces Derived that are extended from Base. It makes it possible to write code such as:
IComparer<object>objectComparer=GetComparer();IComparer<string>stringComparer=objectComparer;Enumerators
An enumerator is an iterator. Enumerators are typically obtained by calling the GetEnumerator() method of an object implementing the IEnumerable interface. Container classes typically implement this interface. However, the foreach statement in C# can operate on any object providing such a method, even if it doesn't implement IEnumerable. This interface was expanded into generic version in .NET 2.0.
The following shows a simple use of iterators in C# 2.0:
// explicit versionIEnumerator<MyType>iter=list.GetEnumerator();while(iter.MoveNext()){Console.WriteLine(iter.Current);}// implicit versionforeach(MyTypevalueinlist){Console.WriteLine(value);}Generator functionality
- This is a feature of C# 2.0.
The .NET 2.0 Framework allowed C# to introduce an iterator that provides generator functionality, using a yieldreturn construct similar to yield in Python.[21] With a yieldreturn, the function automatically keeps its state during the iteration.
// Method that takes an iterable input (possibly an array)// and returns all even numbers.publicstaticIEnumerable<int>GetEven(IEnumerable<int>numbers){foreach(intiinnumbers){if(i%2==0){yieldreturni;}}}// using the method to output only even numbers from the arraystaticvoidMain(){int[]numbers={1,2,3,4,5,6};foreach(intiinGetEven(numbers)){Console.WriteLine(i);// outputs 2, 4 and 6}}LINQ
- This is a feature of C# 3.0 and .NET Framework 3.0.
LINQ, short for Language Integrated Queries, is a .NET Framework feature which simplifies the handling of data. Mainly it supports querying of arrays, collections, and databases. It introduces binders, which makes it easier to access to databases and their data.
Query syntax
LINQ query syntax was introduced in C# 3.0 and supports SQL-like queries.
List<int>list=newList<int>{2,7,1,3,9};IEnumerable<int>result=fromiinlistwherei>1selecti;// Equivalent to:IEnumerable<int>result=list.Where(i=>i>1).Select(i=>i)The statements are compiled into method calls, whereby almost only the names of the methods are specified. Which methods are ultimately used is determined by normal overload resolution. Thus, the result of the translation is affected by the symbols in scope.
What differs from SQL is that the from-statement comes first and not last as in SQL. This seems more natural writing in C# and supports "Intellisense" (Code completion in the editor).
Anonymous methods
Anonymous methods, (lambda expressions), is a feature that allows programmers to write inline closure-like functions.
C# supports various ways to create anonymous methods.
Anonymous delegates
- This is a feature of C# 2.0.
Anonymous delegates are function pointers that hold anonymous methods. The purpose is to make it simpler to use delegates by simplifying function assignment. Instead of declaring a separate method in code the programmer can use the syntax to write the code inline and the compiler generates an anonymous function for it.
Func<int,int>f=delegate(intx){returnx*2;};Lambda expressions
- This is a feature of C# 3.0.
Lambda expressions provide a simple syntax for inline functions that are similar to closures. Functions with parameters infer the type of the parameters if other is not explicitly specified.
// [arguments] => [method-body]// With parametersn=>n==2(a,b)=>a+b(a,b)=>{a++;returna+b;}// With explicitly typed parameters(inta,intb)=>a+b// No parameters()=>return0// Assigning lambda to delegateFunc<int,int,int>f=(a,b)=>a+b;Multi-statement lambdas have bodies enclosed by braces and inside of them code can be written as in standard methods.
(a,b)=>{a++;returna+b;}Lambda expressions can be passed as arguments directly in method calls similar to anonymous delegates but with a cleaner syntax.
varlist=stringList.Where(n=>n.Length>2);Lambda expressions are compiler-generated methods passed via delegates. These methods are reserved for the compiler and cannot be used in any other context.
Extension methods
- This is a feature of C# 3.0.
Extension methods are syntactic sugar providing the illusion of adding new methods to an existing class outside its definition. In practice, an extension method is a static method that is callable as if it were an instance method; the receiver of the call is bound to the first parameter of the method, decorated with keyword this:
publicstaticclassStringExtensions{publicstaticstringLeft(thisstrings,intn){returns.Substring(0,n);}}strings="foo";s.Left(3);// same as StringExtensions.Left(s, 3);Local functions
- This is a feature of C# 7.0.
Local functions can be defined in the body of another method, constructor or property's getter and setter. Such functions have access to all variables in the enclosing scope, including parent method local variables. They are in scope for the entire method, regardless of whether they are invoked before or after their declaration. Access modifiers (public, private, protected) cannot be used with local functions. They do not support function overloading, which means two local functions in the same method cannot have the same name even if the signatures don't overlap.[22] After a compilation, a local function is transformed into a private static method, but when defined it cannot be marked static.[23]
In the example below, the Sum method is a local function inside Main method. So it can be used only inside its parent method Main:
staticvoidMain(string[]args){intSum(intx,inty){returnx+y;}Console.WriteLine(Sum(10,20));Console.ReadKey();}Miscellaneous
Closure blocks
C# implements closure blocks by means of the using statement. The using statement accepts an expression which results in an object implementing IDisposable, and the compiler generates code that guarantees the object's disposal when exiting the scope of the using-statement. The using statement is syntactic sugar. It makes the code more readable than the equivalent try...finally block.
publicvoidFoo(){using(FileStreambar=File.Open("Foo.txt")){// do some workthrownewException();// bar will still get properly disposed.}}Thread synchronization
C# provides the lock statement, which is another example of beneficial syntactic sugar. It works by marking a block of code as a critical section by mutual exclusion of access to a provided object. Like the using statement, the compiler generates a try...finally block in its place.
privatestaticStreamWriter_writer;publicvoidConcurrentMethod(){lock(_writer){_writer.WriteLine("Line 1.");_writer.WriteLine("Followed by line 2.");}}Attributes
Attributes are entities of data that are stored as metadata in the compiled assembly, similar to Java annotations. An attribute can be added to types and members like properties and methods. Attributes can be used for better maintenance of preprocessor directives.
[CompilerGenerated]publicclass$AnonymousType$120{[CompilerGenerated]publicstringName{get;set;}}The .NET Framework comes with predefined attributes that can be used. Some of them serve an important role at runtime, while others are just for syntactic decoration in code like CompilerGenerated. It only marks that it is a compiler-generated element. Programmer-defined attributes can also be created.
An attribute is essentially a class that inherits from the System.Attribute class. By convention, attribute classes end with "Attribute" in their name. This is not required when using it.
publicclassEdibleAttribute:Attribute{publicEdibleAttribute():base(){}publicEdibleAttribute(boolisNotPoisonous){this.IsPoisonous=!isNotPoisonous;}publicboolIsPoisonous{get;set;}}Showing the attribute in use using the optional constructor parameters.
[Edible(true)]publicclassPeach:Fruit{// Members if any}Preprocessor
C# features "preprocessor directives"[24] (though it does not have an actual preprocessor) based on the C preprocessor that allows programmers to define symbols, but not macros. C# does not use the C preprocessor, but evaluates the code directly as if the preprocessor were there. Conditionals such as #if, #endif, and #else are provided, but code inclusion directives like #include and #embed are not supported.
Directives such as #region give hints to editors for code folding. The #region block must be terminated with a #endregion directive.
publicclassFoo{#region ConstructorspublicFoo(){}publicFoo(intfirstParam){}#endregion#region MethodspublicvoidIntBar(intfirstParam){}publicvoidStrBar(stringfirstParam){}publicvoidBoolBar(boolfirstParam){}#endregion}Code comments
C# utilizes a double slash (//) to indicate the rest of the line is a comment.
publicclassFoo{// a commentpublicstaticvoidBar(intfirstParam){}// Also a comment}Multi-line comments can be indicated by a starting slash/asterisk (/*) and ending asterisk/forward slash (*/).
publicclassFoo{/* A multi-line comment */publicstaticvoidBar(intfirstParam){}}Comments do not nest. These are two single comments:
// Can put /* */ */ */ /* /*/* Can put /* /* /* but it ends with */Single-line comments beginning with three slashes are used for XML documentation. This, however, is a Visual Studio convention and is not part of the language definition:
/// <summary>/// This class is very classy./// </summary>XML documentation comments
C#'s documentation comments[25] are similar to Java's Javadoc, but based on XML. Two methods of documentation are supported by the compiler.
Single-line documentation comments, such as those commonly found in Visual Studio generated code, are indicated on a line beginning with ///.
publicclassFoo{/// <summary>A summary of the method.</summary>/// <param name="firstParam">A description of the parameter.</param>/// <remarks>Remarks about the method.</remarks>publicstaticvoidBar(intfirstParam){}}Multi-line documentation comments, while defined in the version 1.0 language specification, were not supported until the .NET 1.1 release.[26] These comments are designated by a starting forward slash/asterisk/asterisk (/**) and ending asterisk/forward slash (*/).[27]
publicclassFoo{/** <summary>A summary of the method.</summary> * <param name="firstParam">A description of the parameter.</param> * <remarks>Remarks about the method.</remarks> */publicstaticvoidBar(intfirstParam){}}Stringent criteria governs white space and XML documentation when using the forward slash/asterisk/asterisk (/**) technique.
This code block:
/** * <summary> * A summary of the method.</summary>*/produces a different XML comment than this code block:[27]
/** * <summary> A summary of the method.</summary>*/Syntax for documentation comments and their XML markup is defined in a non-normative annex of the ECMA C# standard. The same standard also defines rules for processing of such comments, and their transformation to a plain XML document with precise rules for mapping of Common Language Infrastructure (CLI) identifiers to their related documentation elements. This allows any C# integrated development environment (IDE) or other development tool to find documentation for any symbol in the code in a certain well-defined way.
Async-await syntax
- This is a feature of C# 5.0 and .NET Framework 4.0.
As of .NET Framework 4 a task library makes it easier to write parallel and multi-threaded applications through tasks.
C# 5.0 has native language support for asynchrony, e.g:
publicstaticclassSomeAsyncCode{publicstaticTask<XDocument>GetContentAsync(){HttpClienthc=newHttpClient();returnhc.GetStringAsync("https://www.contoso.com/").ContinueWith((task)=>{stringresponseBodyAsText=task.Result;returnXDocument.Parse(responseBodyAsText);});}}vart=SomeAsyncCode.GetContentAsync().ContinueWith((task)=>{XDocumentxmlDocument=task.Result;});t.Start();The same logic written in the async-await syntax:
publicstaticclassSomeAsyncCode{publicstaticasyncTask<XDocument>GetContentAsync(){HttpClienthc=newHttpClient();stringresponseBodyAsText=awaithc.GetStringAsync("https://www.contoso.com/");returnXDocument.Parse(responseBodyAsText);}}XDocumentxmlDocument=awaitSomeAsyncCode.GetContentAsync();// The Task will be started on call with await.Dialects
Spec#
Spec# is a dialect of C# developed in parallel with the official implementation. It extends C# with specification language features and presents a possible future feature to the C# language. It adds syntax for the code contracts API that was introduced in .NET Framework 4.0. Spec# is developed by Microsoft Research.
This sample shows two of the basic structures that are used when adding contracts to code.
staticvoidMain(string![]args)requiresargs.Length>0{foreach(stringarginargs){}}!is used to make a reference type non-nullable, e.g. it is not possible to set the value to null. This in contrast of nullable types which allow value types to be set as null.requiresindicates a condition that must be followed in the code. In this case the length of args is not allowed to be zero or less.
Non-nullable types
Spec# extends C# with non-nullable types that checks so the variables of nullable types that has been set as non-nullable are not null. If is null then an exception is thrown.
string!inputIn use:
publicTest(string!input){...}Preconditions
Preconditions are checked before a method is executed.
publicTest(inti)requiresi>0;{this.i=i;}Postconditions
Postconditions are conditions that are ensured to be correct when a method has been executed.
publicvoidIncrement()ensuresi>0;{i++;}Checked exceptions
Spec# adds checked exceptions like those in Java.
// SomeException extends ICheckedExceptionpublicvoidDoSomething()throwsSomeException{...}Checked exceptions may be inconvenient, because when a lower-level function adds a new exception type, the whole chain of methods using this method at some nested lower level must also change its contract. This violates the open/closed principle.[28] However, checked exceptions are designed to be immediately handled rather than continuously thrown up the stack.
See also
References
- ↑"C# Coding Conventions". Microsoft Learn. sec. Naming conventions. Archived from the original on January 16, 2023.
- 12Wagner, Bill. "C# Keywords". docs.microsoft.com. Retrieved August 26, 2022.
- ↑Schildt, Herbert (December 30, 2008), C# 3.0: The Complete Reference, ISBN 9780071588416
- ↑Deitel, Harvey M.; Deitel, Paul J. (November 21, 2005), C# for programmers, ISBN 9780132465915
- ↑Wagner, Bill. "C# Keywords". docs.microsoft.com. Retrieved August 26, 2022.
- 12Wagner, Bill. "Integral numeric types". learn.microsoft.com. Retrieved October 27, 2024.
- ↑Wagner, Bill. "Floating-point numeric types". learn.microsoft.com. Retrieved October 27, 2024.
- ↑Wagner, Bill. "char". learn.microsoft.com. Retrieved October 27, 2024.
- 12Wagner, Bill. "Strings and string literals". learn.microsoft.com. Retrieved October 27, 2024.
- 12Wagner, Bill. "Declaration statements". learn.microsoft.com. Retrieved October 27, 2024.
- ↑Wagner, Bill. "Assignment operators". learn.microsoft.com. Retrieved October 27, 2024.
- ↑Wagner, Bill. "readonly". learn.microsoft.com. Retrieved October 27, 2024.
- ↑"Exploring C# 10: Save Space with File-Scoped Namespaces". Dave Brock. October 5, 2021. Retrieved November 19, 2024.
- ↑Pointer types (C# Programming Guide)
- 12Archer, Part 2, Chapter 4:The Type System
- ↑"Generics (C# Programming Guide)". Microsoft. Retrieved August 7, 2011.
- ↑"An Introduction to C# Generics". Microsoft.
- ↑"Differences Between C++ Templates and C# Generics". Microsoft.
- ↑"An Introduction to C# Generics". Microsoft. January 2005. Retrieved June 18, 2009.
- ↑ قيود على معلمات النوع (دليل برمجة C#) في Microsoft MSDN
- ↑ "yield" . مرجع لغة C# . مايكروسوفت . تم الاطلاع عليه في 26 أبريل 2009 .
- ↑ "إطار عمل .NET - ما الجديد في C# 7.0" . msdn.microsoft.com . تم الاطلاع عليه بتاريخ 8 أبريل 2017 .
- ↑ "أفكار حول الدوال المحلية في لغة C# 7" . أنطون سيزيكوف . 15 أبريل 2016. تم الاطلاع عليه في 8 أبريل 2017 .
- ↑ "توجيهات المعالج المسبق في لغة C#" . مرجع لغة C# . مايكروسوفت . تم الاطلاع عليه في 18 يونيو 2009 .
- ↑ "تعليقات على التوثيق" . مايكروسوفت ليرن . 15 يونيو 2023.
- ↑ هورتون، أنسون (11 سبتمبر 2006). "أسئلة وأجوبة حول تعليقات توثيق XML في لغة C#" . تم الاطلاع عليه في 11 ديسمبر 2007 .
- 1 2 "محددات علامات التوثيق" . مرجع مبرمج لغة C# . مايكروسوفت . مؤرشف من الأصل في 20 ديسمبر 2008. تم الاطلاع عليه في 18 يونيو 2009 .
- ↑ مارتن، روبرت سي. (11 أغسطس 2008). "7 معالجة الأخطاء، استخدام الاستثناءات غير المُدققة". الكود النظيف: دليل لحرفية البرمجيات الرشيقة . برنتيس هول إنترناشونال. ISBN 978-0132350884.
- آرتشر، توم (2001). داخل لغة سي شارب . مطبعة مايكروسوفت. رقم ISBN 0-7356-1288-9.
- بارت دي سميت على Spec# مؤرشف في 29 أكتوبر 2010، على Wayback Machine
روابط خارجية
- لغة البرمجة سي شارب
- بناء جملة لغة البرمجة
