انواع شمارشي در C#

در اين درس با انواع شمارشي (Enumerator Types) در زبان C# آَشنا خواهيم شد. مطالب مورد بررسي در اين درس به شرح زير مي‌باشند :

درك و فهم يك نوع شمارشي يا يك enum
ساخت يك نوع شمارشي جديد
چگونگي استفاده از انواع شمارشي
آشنايي با متدهاي مختلف موجود در System.Enum

enmu
فرم خاصي از انواع مقداري (Value Type) است كه از System.Enum مشتق شده و امكان پيمايش درون مجموعه‌اي مشخص را با استفاد از اعداد صحصيح براي ما فراهم مي‌نمايد. با استفاده از enum مي‌توان مجموعه‌اي از مقادير ثابت را تعريف نمود كه اين مقادير ثابت با استفاده از يك عدد صحيح قابل دسترسي هستند.

استفاده از enum در برنامه‌ها باعث بالا رفتن خوانايي برنامه مي‌شود، چراكه با استفاده از آنها مي‌توان با مجموعه‌اي از اعداد صحيح ترتيبي (Sequential) ، با عناويني تعريف شده، كار كرد. براي مثال، در اعلان يك enum، ما مجموعه‌اي از نامهاي مورد نظر را تعريف مي‌نماييم و در برنامه مي‌توانيم از اين نامها بصورت ترتيبي استفاده نماييم. Enum به هر يك از عناصر موجود در اين مجموعه عددي را تخصيص مي‌دهد كه شروع اين عدد مي‌تواند توسط برنامه‌نويس نيز معين گردد. سپس با استفاده از نام عناصر موجود در enum و يا با استفاده از اعدادي كه به هر يك از اين عناصر تخصيص داده شده، مي‌توان enum را پيمايش نمود و به عناصر آن دسترسي داشت.

همانطور كه گفته شد، enum يك نوع مقداري (Value Type) است، از اينرو ارث‌بري در مورد آن معنايي ندارد. مساوي قرار دادن دو enum نيز، مقادير يكي را در ديگري كپي مي‌كند. همانطور كه در اين درس، و در منابع ديگر، خواهيد يافت، دسترسي به انواع شمارشي در C# با استفاده از دو كلمه enum و Enum امكان پذير است. در C# نوع شمارشي enum از نوع BCL خود يعني Enum ارث‌بري مي‌كند ! با استفاده از enum يك نوع شمارشي جديد توليد مي‌شود و با استفاده از Enum، مي‌توان به پياده‌سازي متدهاي استاتيك انواع شمارشي پرداخت.

ايجاد يك نوع شمارشي
.Net Framework BCL
حاويenum ها و مثالهاي متعددي از استفادة آنها مي‌باشد. براي مثال هرگاه كه از MessageBox بر روي فرمي استفاده مي‌شود، مي‌توان از MessageBoxIcon كه يك نوع شمارشي است استفاده نمود.

علاوه بر انواع شمارشي تعريف شده و موجود در .Net Framework، زمانهايي نيز وجود دارند كه مي‌خواهيم مجموعه‌اي از عناصر را تعريف كرده و از آنها استفاده نماييم. براي دسترسي به عناصري از نوع صحيح، استفاده از enum باعث خوانا شدن برنامه مي‌گردد.
نحوه اعلان يك enum در حالت كلي بصورت زير است :

كد:

enum
            {
                        // Enumeration list
            {



در مثال 1-17 كه در زير ملاحظه مي‌كنيد، نحوه اعلان و استفاده از enum مشخص شده است.

مثال 1-17 : نحوه اعلان يك enum

كد:

using System;

// declares the enum
public enum Volume
{
   Low,
   Medium,
   High
}

// demonstrates how to use the enum

class EnumSwitch
{
   static void Main()
   {
      // create and initialize
      // instance of enum type
      Volume myVolume = Volume.Medium;

      // make decision based
      // on enum value
      switch (myVolume)
      {
         case Volume.Low:
            Console.WriteLine("The volume has been turned Down.");
            break;
         case Volume.Medium:
            Console.WriteLine("The volume is in the middle.");
            break;
         case Volume.High:
            Console.WriteLine("The volume has been turned up.");
            break;
      }
      Console.ReadLine();
   }
}



در مثال 1-17 نمونه‌اي از اعلان يك enum را مشاهده مي‌نماييد. همانطور كه ديده مي‌شود، اعلان يك نوع شمارشي با استفاده از كلمه كليدي enum صورت گرفته و سپس به دنبال آن نام اين مجموعه مشخص مي‌شود. درون كروشه‌هاي باز و بسته { } نيز، عناصر نوع شمارشي اعلان مي‌گردند.


ادامه نوشته

برخورد با استثناها (Exception Handling)

در اين درس با چگونگی برخورد با استثناها (يا خطاهاي غير قابل پيش‌بيني) در زبان برنامه‌سازي C# آشنا مي‌شويم. اهداف ما در اين درس بشرح زير مي‌باشد :
1)
درک و فهم صحيح يک استثناء يا Exception
2)
پياده‌سازي يک روتين براي برخورد با استثناها بوسيله بلوک try/catch
3)
آزادسازي منابع تخصيص داده شده به يک برنامه در يک بلوک finally

استثناها، در حقيقت خطاهاي غير منتظره در برنامه‌هاي ما هستند. اکثراً، مي‌توان و بايد روشهايي را جهت برخورد با خطاهای موجود در برنامه در نظر گرفت و آنها را پياده‌سازی کرد. بعنوان مثال، بررسي و تاييد داده‌های ورودی کاربران، بررسی اشياء تهی يا Null و يا بررسی نوع بازگشتی متد ها، مي‌توانند از جمله مواردی باشند که بايد مورد بررسی قرار گيرند. اين خطاها، خطاهايی معمول و رايجی هستند که اکثر برنامه‌نويسان از آنها مطلع بوده و راههايی را برای بررسی آنها در نظر مي‌گيرند تا از وقوع آنها جلوگيری نمايند.

اما زمانهايي وجود دارند که از اتفاق افتادن يک خطا در برنامه بی اطلاع هستيد و انتظار وقوع خطا در برنامه را نداريد. بعنوان مثال، هرگز نمي‌‌توان وقوع يک خطای I/O را پيش‌بينی نمود و يا کمبود حافظه برای اجرای برنامه و از کار افتادن برنامه به اين دليل. اين موارد بسيار غير منتظره و ناخواسته هستند، اما در صورت وقوع بهتر است بتوان راهی برای مقابله و برخورد با آنها پيدا کرده و با آنها برخورد نمود. در اين جاست که مسئله برخورد با استثناها (Exception Handling) مطرح مي‌شود.

هنگاميکه استثنايی رخ مي‌دهد، در اصطلاح مي‌گوئيم که اين استثناء، thrown شده است. در حقيقت thrown، شیء‌ای است مشتق شده از کلاس System.Exception که اطلاعاتی در مورد خطا يا استثناء رخ داده را نشان مي‌دهد. در قسمتهای مختلف اين درس با روش مقابله با استثناها با استفاده از بلوک های try/catch آشنا خواهيد شد.

کلاس System.Exception حاوی تعداد بسيار زيادی متد و property است که اطلاعات مهمی در مورد استثناء و خطای رخ داده را در اختيار ما قرار مي‌دهد. برای مثال، Message يکی از property های موجود در اين کلاس است که اطلاعاتی درباره نوع استثناء رخ داده در اختيار ما قرار مي‌دهد. StackTrace نيز، اطلاعاتی در مورد Stack (پشته) و محل وقوع خطا در Stack در اختيار ما قرار خواهد داد.

تشخيص چنين استثناهايی، دقيقاً با روتين‌های نوشته شده توسط برنامه‌نويس در ارتباط هستند و بستگی کامل به الگوريتمی دارد که وی برای چنين شرايطی در نظر گرفته است. برای مثال، در صورتيکه با استفاده از متد System.IO.File.OpenRead()، اقدام به باز کردن فايلی نماييم، احتمال وقوع (Thrown) يکی از استثناهای زير وجود دارد :

كد:

SecurityException
ArgumentException
ArgumentNullException
PathTooLongException
DirectoryNotFoundException
UnauthorizedAccessException
FileNotFoundException
NotSupportedException



با نگاهی بر مستندات .Net Framework SDK، به سادگی مي‌توان از خطاها و استثناهايی که ممکن است يک متد ايجاد کند، مطلع شد. تنها کافيست به قسمت Reference/Class Library رفته و مستندات مربوط به Namespace/Class/Method را مطالعه نماييد. در اين مستندات هر خطا دارای لينکی به کلاس تعريف کننده خود است که با استفاده از آن مي‌توان متوجه شد که اين استثناء به چه موضوعی مربوط است. پس از اينکه از امکان وقوع خطايي در قسمتی از برنامه مطلع شديد، لازم است تا با استفاده از مکانيزمی صحيح به مقابله با آن بپردازيد.

هنگاميکه يک استثناء در اصطلاح thrown مي‌شود (يا اتفاق مي‌افتد) بايد بتوان به طريقی با آن مقابله نمود. با استفاده از بلوکهای try/catch مي‌توان چنين عملی را انجام داد. پياده‌سازی اين بلوکها بدين شکل هستند که، کدی را که احتمال توليد استثناء در آن وجود دارد را در بلوک try، و کد مربوط به مقابله با اين استثناء رخ داده را در بلوک catch قرار مي‌دهيم. در مثال 1-15 چگونگی پياده‌سازی يک بلوک try/catch نشان داده شده است. بدليل اينکه متد OpenRead() احتمال ايجاد يکی از استثناهای گفته شده در بالا را دارد، آنرا در بلوک try قرار داده ايم. در صورتيکه اين خطا رخ دهد، با آن در بلوک catch مقابله خواهيم کرد. در مثال 1-15 در صورت بروز استثناء، پيغامی در مورد استثناء رخ داده و اطلاعاتی در مورد محل وقوع آن در Stack برای کاربر بر روی کنسول نمايش داده مي‌شود.

نکته : توجه نماييد که کليه مثالهای موجود در اين درس به طور تعمدی دارای خطاهايی هستند تا شما با نحوه مقابله با استثناها آشنا شويد

ادامه نوشته

رخدادها و delegate ها در C#    - قسمت دوم

اعلان Delegate
در مثال ما، متد Tick از واسط Tickable از نوع void بود و هيچ پارامتري دريافت نمي‌كرد :

كد:

interface Tickable
{
    void Tick();
}

براي اين متد مي‌توان delegate ي تعريف نمود كه ويژگيهاي آنرا داشته باشد :

كد:

delegate void Tick();



همانطور كه قبلاً نيز گفته شد، اين عمل نوع جديدي را ايجاد مي‌نمايد كه مي‌توان از آن همانند ساير انواع استفاده نمود. مثلاً مي‌توان آنرا بعنوان پارامتري براي يك متد در نظر گرفت :

كد:

void Example(Tick param)
{
   

}



فراخواني delegate
قدرت و توانايي delegate زماني مشهود مي‌گردد كه مي‌خواهيد از آن استفاده نماييد. براي مثال، با متغير param در مثال قبل چكار مي‌توانيد انجام دهيد؟ اگر param متغيري از نوع int بود، از مقدار آن استفاده مي‌كرديد و با استفاده از عملگرهايي نظير +، - و يا عملگرهاي مقايسه‌اي، عملي خاص را بر روي آن انجام مي‌داديد. اما حال كه param متغيري از نوع int نيست، چه مي‌كنيد؟ متغير param يك delegate است و همانطور كه گفته شد، delegate انتزاعي از يك متد است، پس هر عملي كه متد انجام مي‌دهد، delegate نيز مي‌تواند انجام دهد. با استفاده از پرانتز، مي‌توان از delegate استفاده نمود :

كد:

void Example(Tick param)
{
    param();
}

نكته : همانطور كه اشاره شد، delegate يكي از انواع مرجعي است از اينرو مقدار آن مي‌تواند برابر با Null باشد. در مثال فوق، اگر مقدار param برابر با Null باشد، كامپايلر خطاي NullReferenceException را ايجاد مي‌نمايد.

همانند متدها، delegate ها بايد بطور كامل و صحيح فراخواني گردند. با توجه به اعلان Tick، در زمان فراخواني اين delegate، مثلاً param، بايد توجه داشت كه هيچ پارامتري را نمي‌توان به آن ارسال نمود و نمي‌توان آنرا به متغيري نسبت داد چراكه اين delegate بصورت void اعلان شده و مقدار بازگشتي ندارد.

كد:

void Example(Tick param)
{
    param(42);                  // خطاي زمان كامپايل رخ مي‌دهد
    int hhg = param();          // خطاي زمان كامپايل رخ مي‌دهد
    Console.WriteLine(param()); // خطاي زمان كامپايل رخ مي‌دهد
}

توجه نماييد كه delegate را به هر نحوي مي‌توانيد اعلان نماييد. براي مثال به نسخة ديگري از Tick توجه كنيد :

كد:

delegate void Tick(int hours, int minutes, int seconds);



اما به ياد داشته باشيد كه همانند متد، در هنگام استفاده از آن بايد پارامترهاي صحيح به آن ارسال نماييد :

كد:

void Example(Tick method)
{
    method(12, 29, 59);
}


با استفاده از delegate مي‌توانيد كلاس Ticker را پياده‌سازي كنيد :

كد:

delegate void Tick(int hours, int minutes, int seconds);
class Ticker
{
   

    public void Attach(Tick newSubscriber)
    {
        subscribers.Add(newSubscriber);
    }
    public void Detach(Tick exSubscriber)
    {
        subscribers.Remove(exSubscriber);
    }
 
    private void Notify(int hours, int minutes, int seconds)
    {
        foreach (Tick method in subscribers)
        {
            method(hours, minutes, seconds);
        }
    }
   

    private ArrayList subscribers = new ArrayList();
}

ساخت نمونه‌هاي جديد از يك delegate
آخرين كاري كه بايد انجام دهيد، ايجاد نمونه‌هاي جديد از delegate ساخته شده است. يك نمونة جديد از يك delegate، تنها انتزاعي از يك متد است كه با نامگذاري آن متد ايجاد مي‌شود.

 

ادامه نوشته

رخدادها و delegate ها در C#    - قسمت اول

نكته مهم قبل از مطالعه اين درس
توجه نماييد، delegate ها و رخدادها بسيار با يكديگر در تعامل‌اند، از اينرو در برخي موارد، قبل از آموزش و بررسي رخدادها، به ناچار، از آنها نيز استفاده شده و يا به آنها رجوع شده است. رخدادها در قسمت انتهايي اين درس مورد بررسي قرار مي‌گيرند، از اينرو در صورتيكه در برخي موارد دچار مشكل شديد و يا درك مطلب برايتان دشوار بود، ابتدا كل درس را تا انتها مطالعه نماييد و سپس در بار دوم با ديدي جديد به مطالب و مفاهيم موجود در آن نگاه كنيد. در اغلب كتابهاي آموزشي زبان C# نيز ايندو مفهوم با يكديگر آورده شده‌اند ولي درك رخدادها مستلزم درك و فراگيري كامل delegate هاست، از اينرو مطالب مربوط به delegate ها را در ابتدا قرار داده‌ام.

هدف ما در اين درس به شرح زير است :
مقدمه
درك اينكه يك delegate چيست؟
اعلان و پياده‌سازي delegate ها
درك سودمندي delegate ها
حل مسئله بدون استفاده از delegate
حل مسئله با استفاده از delegate
اعلان delegate ها (بخش پيشرفته)
فراخواني delegate ها (بخش پيشرفته)
ايجاد نمونه‌هاي جديد از يك delegate (بخش پيشرفته)
درك اينكه يك رخداد يا يك event چيست؟
اعلان رخدادها
نكات و توضيحات پيشرفته
ثبت شدن در يك رخداد
لغو عضويت در يك رخداد
فراخواني رخدادها
مثالي پيشرفته از استفاده رخدادها در فرمهاي ويندوز
نكات كليدي درباره رخدادها و delegate ها
منابع مورد استفاده
مقدمه‌اي بر رخداد‌ها و
delegate ها
در گذشته، پس از اجراي يك برنامه، برنامه مراحل اجراي خود را مرحله به مرحله اجرا مي‌نمود تا به پايان برسد. در صورتيكه نياز به ارتباط و تراكنش با كاربر نيز وجود داشت، اين امر محدود و بسيار كنترل شده صورت مي‌گرفت و معمولاً ارتباط كاربر با برنامه تنها پر كردن و يا وارد كردن اطلاعات خاصي در فيلدهايي مشخص بود.

امروزه با پبشرفت كامپيوتر و گسترش تكنولوژيهاي برنامه نويسي و با ظهور رابطهاي كاربر گرافيكي (GUI) ارتباط بين كاربر و برنامه بسيار گسترش يافته و ديگر اين ارتباط محدود به پر كردن يكسري فيلد نيست، بلكه انواع عمليات از سوي كاربر قابل انجام است. انتخاب گزينه‌اي خاص در يك منو، كليك كردن بر روي دكمه‌ها براي انجام عملياتي خاص و ... . رهيافتي كه امروزه در برنامه‌نويسي مورد استفاده است، تحت عنوان "برنامه‌نويسي بر پايه رخدادها" (Event-Based Programming) شناخته مي‌شود. در اين رهيافت برنامه همواره منتظر انجام عملي از سوي كاربر مي‌ماند و پس از انجام عملي خاص، رخداد مربوط به آن را اجرا مي‌نمايد. هر عمل كاربر باعث اجراي رخدادي مي‌شود. در اين ميان برخي از رخدادها بدون انجام عملي خاص از سوي كاربر اجرا مي‌شوند، همانند رخدادهاي مربوط به ساعت سيستم كه مرتباً در حال اجرا هستند.

رخدادها (Events) بيان اين مفهوم هستند كه در صورت اتفاق افتادن عملي در برنامه، كاري بايد صورت گيرد. در زبان C# مفاهيم Event و Delegate دو مفهوم بسيار وابسته به يكديگر هستند و با يكديگر در تعامل مي‌باشند. براي مثال، مواجهه با رخدادها و انجام عمل مورد نظر در هنگام اتفاق افتادن يك رخداد، نياز به يك event handler دارد تا در زمان بروز رخداد، بتوان به آن مراجعه نمود. Event handler ها در C# معمولاً با delegate ها ساخته مي‌شوند.

از delegate ، مي‌توان به عنوان يك Callback ياد نمود، بدين معنا كه يك كلاس مي‌تواند به كلاسي ديگر بگويد : "اين عمل خاص را انجام بده و هنگاميكه عمليات را انجام دادي منرا نيز مطلع كن". با استفاده از delegate ها، همچنين مي‌توان متدهايي تعريف نمود كه تنها در زمان اجرا قابل دسترسي باشند.

ادامه نوشته

واسطها (Interfaces)


در اين درس با واسطها در زبان C# آشنا خواهيم شد. اهداف اين درس بشرح زير مي‌باشند :
1-
آشنايي با مفهوم كلي واسطها
2-
تعريف يك واسط
3-
استفاده از يك interface
4-
پياده‌سازي ارث‌بري در interface ها
5-
نكات مهم و پيشرفته
6-
مثالي كاربردي از واسطها
7-
منابع مورد استفاده

واسطها از لحاظ ظاهري بسيار شبيه به كلاس هستند با اين تفاوت كه داراي هيچ گونه پياده‌سازي نمي‌باشند. تنها چيزي كه در interface به چشم مي‌خورد تعاريفي نظير رخدادها، متدها، انديكسرها و يا property ها است. يكي از دلايل اينكه واسطها تنها داراي تعاريف هستند و پياده‌سازي ندارند آنست كه يك interface مي‌توان توسط چندين كلاس يا property مورد ارث‌بري قرار گيرد، از اينرو هر كلاس يا property خواستار آنست كه خود به پياده‌سازي اعضا بپردازد.

حال بايد ديد چرا با توجه به اينكه interface ها داراي پياده‌سازي نيستند مورد استفاده قرار مي‌گيرند يا بهتر بگوئيم سودمندي استفاده از interface ها در چيست؟ تصور كنيد كه در يك برنامه با مولفه‌هايي سروكار داريد كه متغيرند ولي داراي فيلدها يا متدهايي با نامهاي يكساني هستند و بايد نام اين متدها نيز يكسان باشد. با استفاده از يك interface مناسب مي‌توان تنها متدها و يا فيلدهاي مورد نظر را اعلان نمود و سپس كلاسها و يا property هاي مورد از آن interface ارث‌بري نمايند. در اين حالت تمامي كلاسها و property ها داراي فيلدها و يا متدهايي همنام هستند ولي هر يك پياده‌سازي خاصي از آنها را اعمال مي‌نمايند.

نكته مهم ديگر درباره interface ها، استفاده و كاربرد آنها در برنامه‌هاي بزرگي است كه برنامه‌ها و يا اشياؤ مختلفي در تماس و تراكنش (transact) هستند. تصور كنيد كلاسي در يك برنامه با كلاسي ديگر در برنامه‌اي ديگر در ارتباط باشد. فرض كنيد اين كلاس متدي دارد كه مقداري از نوع int بازميگرداند. پس از مدتي طراح برنامه به اين نتيجه مي‌رسد كه استفاده از int پاسخگوي مشكلش نيست و بايد از long استفاده نمايد. حال شرايط را در نظر بگيريد كه براي تغيير يك چنين مسئله ساده‌اي چه مشكل بزرگي پيش خواهد آمد. تمامي فيلدهاي مورتبط با اين متد بايد تغيير داده شوند. در ضمن از مسئله side effect نيز نمي‌توان چشم پوشي كرد.( تاثيرات ناخواسته و غير منتظره و يا به عبارتي پيش بيني نشده كه متغير يا فيلدي بر روي متغير يا فيلدي ديگر اعمال مي‌كند، در اصطلاح side effect گفته مي‌شود.) حال فرض كنيد كه در ابتدا interface اي طراحي شده بود. درصورت اعمال جزئيترين تغيير در برنامه مشكل تبديل int به long قابل حل بود، چراكه كاربر يا برنامه و در كل user برنامه در هنگام استفاده از يك interface با پيادهسازي پشت پرده آن كاري ندارد و يا بهتر بگوئيم امكان دسترسي به آن را ندارد. از اينرو اعمال تغييرات درون آن تاثيري بر رفتار كاربر نخواهد داشت و حتي كاربر از آن مطلع نيز نمي‌شود. در مفاهيم كلي شيء گرايي، interface ها يكي از مهمترين و كاربردي ترين اجزاء هستند كه در صورت درك صحيح بسيار مفيد واقع مي‌شوند. يكي از مثالهاي مشهود درباره interface ها (البته در سطحي پيشرفته تر و بالاتر) رابطهاي كاربر گرافيكي (GUI) هستند. كاربر تنها با اين رابط سروكار دارد و كاري به نحوه عمليات پشت پرده آن ندارد و اعمال تغييرات در پياده‌سازي interface كاربر را تحت تاثير قرار نمي‌دهد.

از ديدگاه تكنيكي، واسطها بسط مفهومي هستند كه از آن به عنوان انتزاع (Abstract) ياد مي‌كنيم. در كلاسهاي انتزاعي (كه با كلمه كليد abstract مشخص مي‌شدند.) سازندة كلاس قدر بود تا فرم كلاس خود را مشخص نمايد : نام متدها، نوع بازگشتي آنها و تعداد و نوع پارامتر آنها، اما بدون پياده‌سازي بدنه متد. يك interface همچنين مي‌تواند داراي فيلدهايي باشد كه تمامي آنها static و final هستند. يك interface تنها يك فرم كلي را بدون پياده‌سازي به نمايش مي‌گذارد.

از اين ديدگاه، يك واسط بيان مي‌دارد كه : " اين فرم كلي است كه تمامي كلاسهايي كه اين واسط را پياده‌سازي مي‌كنند، بايد آنرا داشته باشند." از سوي ديگر كلاسها و اشياء ديگري كه از كلاسي كه از يك واسط مشتق شده استفاده مي‌كنند، مي‌دانند كه اين كلاس حتماً تمامي متدها و اعضاي واسط را پياده‌سازي مي‌كند و مي‌توانند به راحتي از آن متدها و اعضا استفاده نمايند. پس به طور كلي مي‌توانيم بگوئيم كه واسطها بمنظور ايجاد يك پروتكل (protocol) بين كلاسها مورد استفاده قرار مي‌گيرند. (همچنان كه برخي از زبانهاي برنامه‌سازي بجاي استفاده از كلمه كليدي interface از protocol استفاده مي‌نمايند.)


به دليل اينكه كلاسها و ساختارهايي كه از interface ها ارث‌بري مي‌كنند موظف به پياده‌سازي و تعريف آنها هستند، قانون و قاعده‌اي در اين باره ايجاد مي‌گردد. براي مثال اگر كلاس A از واسط IDisposable ارث‌بري كند، اين ضمانت بوجود مي‌آيد كه كلاس A داراي متد Dispose() است، كه تنها عضو interface نيز مي‌باشد. هر كدي كه مي‌خواهد از كلاس A استفاده كند، ابتدا چك مي‌نمايد كه آيا كلاس A واسط IDisposable را پياده‌سازي نموده يا خير. اگر پاسخ مثبت باشد آنگاه كد متوجه مي‌شود كه مي‌تواند از متد A.Dispose() نيز استفاده نمايد. در زير نحوه اعلان يك واسط نمايش داده شده است.

كد:

interface IMyInterface
{
void MethodToImplement();
}



در اين مثال نحوه اعلان واسطي با نام IMyInterface نشان داده شده است. يك قاعده (نه قانون!) براي نامگذاري واسطها آنست كه نام واسطها را با "I" آغاز كنيم كه اختصار كلمه interface است. در interface اين مثال تنها يك متد وجود دارد. اين متد مي‌توان هر متدي با انواع مختلف پارامترها و نوع بازگشتي باشد. توجه نماييد همانطور كه گفته شد اين متد داراي پياده‌سازي نيست و تنها اعلان شده است. نكته ديگر كه بايد به ان توجه كنيد آنست كه اين متد به جاي داشتن {} به عنوان بلوك خود، داراي ; در انتهاي اعلان خود مي‌باشد. علت اين امر آنست كه interface تنها نوع بازگشتي و پارامترهاي متد را مشخص مي‌نمايد و كلاس يا شي‌اي كه از آن ارث مي‌برد بايد آنرا پياده‌سازي نمايد. مثال زير نحوه استفاده از اين واسط را نشان مي‌دهد.

مثال 1-13 : استفاده از واسطها و ارث‌بري از آنها

كد:

class InterfaceImplementer : IMyInterface
{
static void Main()
{
InterfaceImplementer iImp = new InterfaceImplementer();
iImp.MethodToImplement();
}
public void MethodToImplement()
{
Console.WriteLine("MethodToImplement() called.");
}
}

در اين مثال، كلاس InterfaceImplementer همانند ارث‌بري از يك كلاس، از واسط IMyInterface ارث‌بري كرده است. حال كه اين كلاس از واسط مورد نظر ارث‌بري كرده است، بايد، توجه نماييد بايد، تمامي اعضاي آنرا پياده‌سازي كند. در اين مثال اين عمل با پياده‌سازي تنها عضو واسط يعني متد MethodToImplement() انجام گرفته است. توجه نماييد كه پياده‌سازي متد بايد دقيقا از لحاظ نوع بازگشتي و تعداد و نوع پارامترها شبيه به اعلان موجود در واسط باشد، كوچكترين تغييري باعث ايجاد خطاي كامپايلر مي‌شود. مثال زير نحوه ارث‌بري واسطها از يكديگر نيز نمايش داده شده است.

مثال 2-13 : ارث‌بري واسطها از يكديگر

كد:

using System;
 
interface IParentInterface
{
void ParentInterfaceMethod();
}
 
interface IMyInterface : IParentInterface
{
void MethodToImplement();
}
 
class InterfaceImplementer : IMyInterface
{
static void Main()
{
InterfaceImplementer iImp = new InterfaceImplementer();
iImp.MethodToImplement();
iImp.ParentInterfaceMethod();
}
 
public void MethodToImplement()
{
Console.WriteLine("MethodToImplement() called.");
}
 
public void ParentInterfaceMethod()
{
Console.WriteLine("ParentInterfaceMethod() called.");
}
}

ادامه نوشته

ساختارها در C# (Struct)

• يك struct يا ساختار (Structure) چيست؟ 
• 
پياده‌سازي ساختارها(Struct) 
• 
استفاده از ساختارها(Struct) 
• 
نكات مهم و مطالب كمكي دربارة struct ها ساختار (struct) چيست؟ همانطور كه با استفاده از كلاسها مي‌توان انواع (types) جديد و مورد نظر را ايجاد نمود، با استفاده ازstruct ها مي‌توان انواع مقداري (value types) جديد و مورد نظر را ايجاد نمود. از آنجائيكه struct ها بعنوان انواع مقداري در نظر گرفته مي‌شوند، از اينرو تمامي اعمال مورد استفاده بر روي انواع مقداري رامي‌توان براي struct ها در نظر گرفت. struct ها بسيار شبيه به كلاس‌ها هستند و مي‌توانند داراي فيلد، متد و property باشند. عموماً ساختارها مجموعه كوچكي از عناصري هستند كه منطقي با يكديگر داراي رابطه مي‌باشند. براي نمونه مي‌توان به ساختار Point موجود در Framework SDK اشاره كرد كه حاوي دو property با نامهاي X و Y استبا استفاده از ساختارها (struct) مي‌توان اشيايي با انواع جديد ايجاد كرد كه اين اشياء مي‌توانند شبيه به انواع موجود (int, float, …) باشند. حال سوال اينست كه چه زماني از ساختارها(struct) بجاي كلاس استفاده مي‌كنيم؟ در ابتدا به نحوه استفاده از انواع موجود در زبان ‍C# توجه نماييد. اين انواع داراي مقادير و عملگرهاي معيني جهت كار با اين مقادير هستند. حال اگر نياز به شي‌اي داريد كه همانند اين انواع رفتار نمايند لازم است تا از ساختارها (struct) استفاده نماييددر ادامه اين مبحث نكات و قوانيني را ذكر مي‌كنيم كه با استفاده از آنها بهتر بتوانيد از ساختارها (struct) استفاده نماييداعلان و پياده‌سازي struct براي اعلان يك struct كافيست تا با استفاده از كلمه كليدي struct كه بدنبال آن نام مورد نظر براي ساختار آمده استفاده كرد. بدنة ساختار نيز بين دو كروشة باز و بسته {} قرار خواهد گرفت. به مثال زير توجه نماييد : مثال 1-12 : نمونه‌اي از يك ساختار (Struct)

كد:

using System; 
struct Point 

public int x; 
public int y; 
public Point(int x, int y) 

this.x = x; 
this.y = y; 

public Point Add(Point pt) 

Point newPt; 
newPt.x = x + pt.x; 
newPt.y = y + pt.y; 
return newPt; 


///

 
/// struct مثالي از اعلان و ساخت يك 
///
 
class StructExample 

static void Main(string[] args) 

Point pt1 = new Point(1, 1); 
Point pt2 = new Point(2, 2); 
Point pt3; 
pt3 = pt1.Add(pt2); 
Console.WriteLine("pt3: {0}:{1}", pt3.x, pt3.y); 

}


ادامه نوشته

انديكسرها در C# (Indexers)


در اين درس با انديكسرها در C# آشنا مي‌شويم. اهداف اين درس به شرح زير مي‌باشند : 
• 
پياده‌سازي انديكسر 
• 
سرريزي انديكسرها (Overload) 
• 
درك چگونگي پياده‌سازي انديكسرهاي چند پارامتري 
• 
خلاصه 
• 
نكات مهم و مطالب كمكي در زمينه انديكسرها انديكسرها انديكسرها مفهومي بسيار ساده در زبان C# هستند. با استفاده از آنها مي‌توانيد از كلاس خود همانند يك آرايه استفاده كنيد. در داخل كلاس مجموعه‌اي از مقادير را به هر طريقي كه مورد نظرتان هست مديريت كنيد. اين اشياؤ مي‌توانند شامل مجموعه‌اي از اعضاي كلاس، يك آرايه ديگر، و يا مجموعه‌اي از ساختارهاي پيچيده داده‌اي باشند، جدا از پياده‌سازي داخلي كلاس، داده‌هاي اين ساختارها از طريق استفاده از انديكسرها قابل دسترسي هستند. به مثالي در اين زمينه توجه كنيد : مثال 11-1 : نمونه‌اي از يك انديكسر

كد:

using System; 
///

 
/// مثالي ساده از يك انديكسر 
///
 
class IntIndexer 

private string[] myData; 
public IntIndexer(int size) 

myData = new string[size]; 
for (int i=0; i < size; i++) 

myData[i] = "empty"; 


public string this[int pos] 

get 

return myData[pos]; 

set 

myData[pos] = value; 


static void Main(string[] args) 

int size = 10; 
IntIndexer myInd = new IntIndexer(size); 
myInd[9] = "Some Value"; 
myInd[3] = "Another Value"; 
myInd[5] = "Any Value"; 
Console.WriteLine("nIndexer Outputn"); 
for (int i=0; i < size; i++) 

Console.WriteLine("myInd[{0}]: {1}", i, myInd[i]); 


}

مثال 11-1 نحوه پياده‌سازي انديكسر را نشان مي‌دهدكلاس IntIndexer داراي آراية رشته‌اي بنام myDataمي‌باشد. اين آرايه، عنصري خصوصي (private) است و كاربران خارجي (external users) نمي‌توانند به آن دسترسي داشته باشند. اين آرايه درون سازندة (constructor) كلاس تخصيص‌دهي مي‌گردد كه در آن پارامتر size از نوع intدريافت مي‌شود، از آرايه myData نمونه‌اي جديد ايجاد مي‌گردد، سپس هر يك از المانهاي آن با كلمه "empty"مقدار‌دهي مي‌گردد

ادامه نوشته

ويژگيها در سی شارپ


در اين درس با ويژگيها (Properties) در زبان C# آشنا خواهيم شد. اهداف اين درس به شرح زير مي‌باشد
• 
موارد استفاده از Property ها 
• 
پياده‌سازي Property 
• 
ايجاد Property فقط خواندني (Read-Only) 
• 
ايجاد Property فقط نوشتني (Write-Only) 

Property 
ها امكان ايجاد حفاظت از فيلدهاي يك كلاس را از طريق خواندن و نوشتن بوسيله Property را فراهم مي‌نمايد. Property ها علاوه بر اينكه از فيلدهاي يك كلاس حفاظت مي‌كنند، همانند يك فيلد قابل دسترسي هستند. بمنظور درك ارزش Property ها بهتر است ابتدا به روش كلاسيك كپسوله كردن متدها توجه نماييدمثال 1-10 : يك نمونه از چگونگي دسترسي به فيلدهاي كلاس به طريقه كلاسيك

كد:

using System; 
public class PropertyHolder 

private int someProperty = 0; 
public int getSomeProperty() 

return someProperty; 

public void setSomeProperty(int propValue) 

someProperty = propValue; 


public class PropertyTester 

public static int Main(string[] args) 

PropertyHolder propHold = new PropertyHolder(); 
propHold.setSomeProperty(5); 
Console.WriteLine("Property Value: {0}", propHold.getSomeProperty()); 
return 0; 

}

مثال 1-10 روش كلاسيك دسترسي به فيلدهاي يك كلاس را نشان مي‌دهد. كلاس PropertyHolderداراي فيلدي است تمايل داريم به آن دسترسي داشته باشيم. اين كلاس داراي دو متدgetSomeProperty() و setSomePropery() مي‌باشد. متد getSomeProperty() مقدار فيلدsomeProperty را باز مي‌گرداند و متد setSomeProperty() مقداري را به فيلد someProperty تخصيص مي‌دهد

ادامه نوشته

_ چند ريختي (Polymorphism)

در اين درس به بررسي چند ريختي در زبان ‍C# خواهيم پرداختاهداف اين درس عبارتند از : 

• 
چند ريختي چيست؟ 
• 
پياده‌سازي متد مجازي (Virtual Method) 
• Override 
كردن متد مجازي 
• 
استفاده از چند ريختي در برنامه‌ها يكي ديگر از مفاهيم پايه‌اي در شي‌گرايي، چند ريختي (Polymorphism) است. با استفاده از اين ويژگي، مي‌توان براي متد كلاس مشتق شده پياده‌سازي متفاوتي از پياده‌سازي متد كلاس پايه ايجاد نمود. اين ويژگي در جايي مناسب است كه مي‌خواهيد گروهي از اشيا‌ء را به يك آرايه تخصيص دهيد و سپس از متد هر يك از آنها را استفاده كنيد. اين اشياء الزاما نبايد از يك نوع شي‌ء باشند. هرچند اگر اين اشياء بواسطه ارث‌بري به يكديگر مرتبت باشند، مي‌توان آنها را بعنوان انواع ارث‌بري شده به آرايه اضافه نمود. اگر هر يك از اين اشياء داراي متدي با نام مشترك باشند، آنگاه مي‌توان هر يك از آنها را جداگانه پياده‌سازي و استفاده نمود. در اين درس با چگونگي انجام اين عمل آشنا مي‌گرديدمتد مجازي (Virtual Method)

كد:

using System; 
  
public class DrawingObject 

public virtual void Draw() 

Console.WriteLine("I'm just a generic drawing object."); 

}


مثال 1-9 كلاس DrawingObject را نشان مي‌دهد. اين كلاس مي‌تواند بعنوان كلاسي پايه چهت كلاسهاي ديگر در نظر گرفته شود. اين كلاس تنها داراي يك متد با نام Draw() مي‌باشد. اين متد داراي پيشوند virtual است. وجود كلمه virtual بيان مي‌دارد كه كلاسهاي مشتق شده از اين كلاس مي‌توانند، اين متد را override نماييد و آنرا به طريقه دلخواه پياده‌سازي كنند.

ادامه نوشته

ارث‌بري كلاس‌ها

در اين درس درباره ارث‌بري در زبان برنامه‌نويسي C# صحبت خواهيم كرد. اهداف اين درس بشرح زير مي‌باشند : 
 
پياده‌سازي كلاسهاي پايه (Baseü Class) 
 
پياده‌سازي كلاسهاي مشتق شده (Derived Class)ü 
 
مقدار دهي كلاسü پايه از طريق كلاس مشتق شده 
 
فراخواني اعضاي كلاس پايهü 
 
پنهان‌سازي اعضايü كلاس پايه ارث‌بري يكي از مفاهيم اساسي و پايه شي‌گرايي است. با استفاده از اين ويژگي امكان استفاده مجدد از كد موجود فراهم مي‌شود. بوسيله استفاده موثر از اين ويژگي كار برنامه‌نويسي آسان‌تر مي‌گرددارث‌بري(Inheritance)

كد:

using System; 
  
public class ParentClass 

public ParentClass() 

Console.WriteLine("Parent Constructor."); 

public void print() 

Console.WriteLine("I'm a Parent Class."); 


public class ChildClass : ParentClass 

public ChildClass() 

Console.WriteLine("Child Constructor."); 

public static void Main() 

ChildClass child = new ChildClass(); 
child.print(); 

}

خروجي اين برنامه بصورت زير است :

كد:

Parent Constructor. 
Child Constructor. 
I'm a Parent Class.


ادامه نوشته

آشنايي با كلاسها در C#



اين درس با كلاسها در زبان C# آشنا خواهيد شد. اهداف اين درس به شرح زير مي‌باشند : 
 
پياده‌سازي سازنده‌ها (Constructors)ü ü درك تفاوت بين اعضاي نمونه (Instance) و استاتيك (Static) 
 
آشنايي با تخريبü كننده‌ها (Destructors) 
 
آشنايي با اعضاي كلاسهاü در تمامي مطالبي كه در اين سايت مشاهده كرده‌ايد، برنامه‌ها داراي كلاس‌هايي بوده‌اند. در حال حاضر بايد درك نسبي از كلاسها و كار آنها و چگونگي ايجاد آنها داشته باشيد. در اين درس مروري بر آموخته‌هاي قبلي از كلاسها خواهيم كرد و نيز با اعضاي كلاسها آشنا مي‌شويميك كلاس با استفاده از كلمه كليدي class كه بدنبال آن نام كلاس آمده باشد، اعلان مي‌گردد و اعضاي اين كلاس درون {} اعلان مي‌گردند. هر كلاس داراي سازنده‌اي مي‌باشد كه در هربار ايجاد نمونه‌اي جديد از آن كلاس، بصورت خودكار فراخواني مي‌گردد. هدف از سازنده، تخصيص‌دهي اعضاي كلاس در زمان ايجاد نمونه‌اي جديد از كلاس است. سازنده‌ها داراي مقادير بازگشتي نبوده و همواره نامي مشابه نام كلاس دارند. مثال 1-7 نمونه‌اي از يك كلاس را نشان مي‌دهد.

كد:

// Namespace اعلان 
using System; 
  
class OutputClass 

string myString; 
// سازنده 
public OutputClass(string inputString) 

myString = inputString; 

 // متد نمونه 
public void printString() 

Console.WriteLine("{0}", myString); 

// تخريب كننده 
~OutputClass() 

// روتيني جهت آزادسازي برخي از منابع سيستم 


// كلاس آغازين برنامه 
class ExampleClass 

// آغاز اجراي برنامه 
public static void Main() 

// OutputClass نمونه‌اي از 
OutputClass outCl = new OutputClass("This is printed by the output class."); 
 // Output فراخواني متد كلاس 
outCl.printString(); 

}

ادامه نوشته

Namespaces ها

اهداف اين درس به شرح زير مي‌باشد : 
 
آشنايي با Namespaceü در زبان C# 
 
چگونگي استفاده از هدايتگر using (using directive)ü 
 
چگونگيü استفاده از هدايتگر alias (alias directive) 
 
اعضاي يك Namespace چه هستند؟ü Namespace ها، المان‌هاي زبان C# هستند كه شما را در سازماندهي كردن برنامه، كمك مي‌كنند. پياده‌سازي Namespaceها در كد برنامه بسيار مفيد است چراكه از ايجاد مشكلات مربوط به استفاده مجدد كد، پيشگيري مي‌نمايدچگونگي ايجاد Namespace به مثال زير توجه نماييد.

كد:

// Namespace اعلان 
using System; 
  
// C# Persian Namespace 
namespace csharp-persian 

// كلاس آغازين برنامه 
class NamespaceCSS 

// آغاز اجراي برنامه 
public static void Main() 

// چاپ خروجي در كنسول 
Console.WriteLine("This is the new C# Persian Namespace."); 


}

مثال 1-6 چگونگي ايجاد يك Namespace را نشان مي‌دهددر اين مثال ما با قرار دادن كلمه كليدي namespace در جلوي csharp-persian يك Namespace جديد ايجاد نموديم. مثال 2-6، Namespace هاي تودرتو را نشان مي‌دهد.

ادامه نوشته