صفحه 2 از 2 نخستنخست 12
نمایش نتایج: از شماره 11 تا 19 , از مجموع 19

موضوع: مقدمه ای بر سی شارپ

  1. #11
    معاونت سایت
    تاریخ عضویت
    2012/06/05
    محل سکونت
    Tabriz
    نوشته ها
    14,398

    پیش فرض

    مقدمه ای بر سی شارپ : قسمت دوازدهم
    کلاس ها در سی شارپ :

    تا بحال در حد کاربرد ، با کلاس ها آشنا شده ایم . اما در این قسمت می خواهیم نگاهی دقیق تر به کلاس ها بیاندازیم.

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

    using System;

    class Data
    {
    public int x;
    }
    class App
    {
    public static void Main()
    {
    Data d1 = new Data();
    d1.x = 1;
    Data d2 = new Data();
    d2.x = 2;
    Console.WriteLine("d1.x = {0}", d1.x);
    Console.WriteLine("d2.x = {0}", d2.x);
    }
    }

    در اینجا کلاس Data تعریف شده است و دارای یک عضو به نام x می باشد. به این نوع داده در کلاس فیلد گفته می شود و هنگامیکه به صورت public معرفی می شود یعنی خارج از کلاس نیز قابل دسترسی است. در کد بالا دو متغیر از کلاس تعریف و مقدار دهی اولیه شده اند. خروجی برنامه به صورت زیر است :

    d1.x = 1
    d2.x = 2

    دلیل این خروجی آن است که هر instance (نمونه) از کلاس منحصر بفرد است و در اینجا نمی توان انتظار داشت که هر دو خروجی یکی شوند.

    برای مقدار دهی اولیه متغیرهایی که به صورت فیلد تعریف می شوند ، بهتر است مقدار دهی آنها را در سازنده ی کلاس (constructor) انجام دهیم.

    class Data
    {
    public int x;
    public Data(){x = 99;}
    }

    همانطور که پیشتر نیز ذکر شد ، متدی که هم نام کلاس است ، سازنده نام می گیرد. یک کلاس می تواند بیش از یک سازنده داشته باشد. برای مثال :

    class Data
    {
    public int x;
    private Data(){}
    public Data(int y){x = y;}
    public Data(int y, int z){x = y + z;}
    }

    از آنجائیکه که سازنده ی بدون پارامتر ذکر شده در کد فوق private تعریف شده است بنابراین خارج از کلاس دیگر قابل دسترسی نمی باشد . بنابراین کدی خارج از کلاس ، تنها می تواند از دو سازنده ی دیگر استفاده کند. برای مثال تعریف دو متغیر جدید از این کلاس به صورت زیر می باشد :

    Data d1 = new Data(44);
    Data d2 = new Data(22, 33);

    سی شارپ به شما اجازه می دهد تا سازنده ها را در یک کلاس توسط کلمه ی کلیدی this نیز فراخوانی کنید یعنی بجای ذکر نام متد سازنده از کلمه ی this استفاده شود .

    اگر می خواهید متغیری را بین نمونه (instance) های مختلف یک کلاس به اشتراک بگذارید کلمه ی کلیدی static وارد صحنه می شود. به مثال زیر توجه کنید :

    using System;

    class Counted
    {
    public static int count = 0;
    public Counted()
    {
    count++;
    }
    public int GetInstanceCount()
    {
    return count;
    }
    }
    class App
    {
    public static void Main()
    {
    Counted d1 = new Counted();
    Console.WriteLine("current total {0}", d1.GetInstanceCount());
    Counted d2 = new Counted();
    Console.WriteLine("current total {0}", d2.GetInstanceCount());
    Console.WriteLine("total {0}", Counted.count);
    }
    }

    باید خاطر نشان کرد که متغیرهای استاتیک توسط نمونه های کلاس قابل دستیابی نیستند و فقط درون کلاس به شکل زیر می توان از آْنها استفاده کرد :

    .

    در مثال فوق دو نمونه از کلاس Counted تعریف شده است. با هر بار فراخوانی کلاس ، خودبخود سازنده اجرا شده و یک عدد به این شمارشگر استاتیک اضافه می شود. همانطور که ذکر شد، برای اینکه بتوان به این متغیر استاتیک در خارج از کد دسترسی پیدا کرد یک متد غیر استاتیک تعریف شده است.

    در مثال فوق تابع GetInstanceCount تنها یک عدد را بر می گرداند. در برنامه نویسی شیء گرا مرسوم است که در این حالت به جای توابع از خواص استفاده شود که به اندازه ی کافی در مورد آنها در قسمت های قبل توضیح داده شد. در این صورت تعریف فوق به صورت زیر در می آید :

    class Counted
    {
    public static int x = 0;
    public Counted()
    {
    x++;
    }
    public int InstanceCount // property
    {
    get{return x;}
    }
    }

    و در این صورت قسمت بعدی کد به صورت زیر اصلاح می شود (فراخوانی خواص ، بدون ذکر پرانتزها بعد از نام آنها صورت می گیرد):

    Counted d1 = new Counted();
    Console.WriteLine("current total {0}", d1.InstanceCount);
    Counted d2 = new Counted();
    Console.WriteLine("current total {0}", d2.InstanceCount);

    اگر یک خاصیت هم خواندنی و هم نوشتنی باشد به صورت زیر تعریف می شود :

    private string name;
    public string Name
    {
    get{return name;}
    set{name = value;}
    }

    فیلدهای پابلیک را می توان خواند و یا تغییر داد. اگر لازم باشد تا کاربر نتواند آنها را تغییر دهد می توان از کلمه ی کلیدی readonly قبل از تعریف آنها استفاده کرد. مثال :

    class Data
    {
    public readonly int x = 42;
    }

  2. #12
    معاونت سایت
    تاریخ عضویت
    2012/06/05
    محل سکونت
    Tabriz
    نوشته ها
    14,398

    New 2

    مقدمه ای بر سی شارپ : قسمت سیزدهم
    با استفاده از ایندکسرها می توان با یک کلاس همانند آرایه ها رفتار کرد. به مثال زیر توجه کنید :

    using System;

    ///
    /// A simple indexer example.
    ///
    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]);
    }
    }
    }

    در مثال فوق نحوه ی تعریف و استفاده از ایندکسرها را می توان مشاهده کرد. کلاس IntIndexer حاوی آرایه ای به نام myData می باشد. بدلیل private بودن آن در خارج از کلاس قابل دسترسی نیست. این آرایه در سازنده ی کلاس (متد IntIndexer) با کلمه ی empty مقدار دهی اولیه شده است.
    عضو بعدی کلاس Indexer می باشد و با کلمه ی کلیدی this و براکتها مشخص شده ست (this[int pos]). همانطور که ملاحظه می فرمایید نحوه ی تعریف ایندکسرها شبیه به تعریف خواص می باشد.

    this [argument list]
    {
    get
    {
    // Get codes goes here
    }
    set
    {
    // Set codes goes here
    }
    }

    خروجی مثال فوق به صورت زیر است :

    myInd[0]: empty
    myInd[1]: empty
    myInd[2]: empty
    myInd[3]: Another Value
    myInd[4]: empty
    myInd[5]: Any Value
    myInd[6]: empty
    myInd[7]: empty
    myInd[8]: empty
    myInd[9]: Some Value

    استفاده از اعداد صحیح روشی است متداول برای دسترسی به اعضای آرایه ها در بسیاری از زبانها اما ایندکسرها در سی شارپ فراتر از این می رود. ایندکسرها را می توان با پارامترهای متعددی تعریف کرد و هر پارامتر با نوعی مختلف (دقیقا همانند پارامترهای ورودی متدها). البته محدودیتی که اینجا وجود دارد در مورد نوع پارامتر ها است که تنها می تواند integers, enums, and strings باشد . بعلاوه قابلیت Overloading ایندکسرها نیز وجود دارد. به همین جهت به آنها آرایه های هوشمند هم گفته می شود (smart arrays) .مثال :

    using System;

    ///
    /// Implements overloaded indexers.
    ///
    class OvrIndexer
    {
    private string[] myData;
    private int arrSize;

    public OvrIndexer(int size)
    {
    arrSize = 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;
    }
    }

    public string this[string data]
    {
    get
    {
    int count = 0;

    for (int i=0; i < arrSize; i++)
    {
    if (myData[i] == data)
    {
    count++;
    }
    }
    return count.ToString();
    }
    set
    {
    for (int i=0; i < arrSize; i++)
    {
    if (myData[i] == data)
    {
    myData[i] = value;
    }
    }
    }
    }

    static void Main(string[] args)
    {
    int size = 10;
    OvrIndexer myInd = new OvrIndexer(size);

    myInd[9] = "Some Value";
    myInd[3] = "Another Value";
    myInd[5] = "Any Value";

    myInd["empty"] = "no value";

    Console.WriteLine("nIndexer Outputn");

    for (int i=0; i < size; i++)
    {
    Console.WriteLine("myInd[{0}]: {1}", i, myInd[i]);
    }

    Console.WriteLine("nNumber of "no value" entries: {0}", myInd["no value"]);
    }
    }

    در مثال فوق اولین ایندکسر با یک پارامتر از نوع اعداد صحیح تعریف شده است و در ایندکسر دوم از نوع رشته.
    خروجی برنامه ی فوق به صورت زیر است :

    myInd[0]: no value
    myInd[1]: no value
    myInd[2]: no value
    myInd[3]: Another Value
    myInd[4]: no value
    myInd[5]: Any Value
    myInd[6]: no value
    myInd[7]: no value
    myInd[8]: no value
    myInd[9]: Some Value

    Number of "no value" entries: 7


    نکته :
    1- امضای (لیست پارامترهای) ایندکسر ها در یک کلاس باید منحصر بفرد باشد .
    2- تعریف یک ایندکسر به صورت استاتیک مجاز نیست.

    در صورت نیاز به ایندکسرهایی با پارمترهای ورودی متعدد می توان به صورت زیر عمل کرد :

    public object this[int param1, ..., int paramN]
    {
    get
    {
    // process and return some class data
    }
    set
    {
    // process and assign some class data
    }
    }

    یک مثال دیگر :

    using System;

    class IndexExample
    {
    string Message;

    public static void Main()
    {
    IndexExample obj=new IndexExample("Welcome");

    /* This will access the String variable Message
    using array like notation
    */
    for(int i=0;i < obj.Length;i++)
    {
    Console.WriteLine(obj[i]);
    }
    obj[obj.Length-1]="e to C#";

    Console.WriteLine(obj.Message);

    }

    public IndexExample(string s)
    {
    Message=s;
    }

    public string this[int i]
    {
    get
    {
    if(i >= 0 && i < Message.Length)
    {
    return Message.Substring(i,1);
    }
    else
    {
    return "";
    }
    }
    set
    {
    if(i >= 0 && i < Message.Length)
    {
    Message=Message.Substring(0,i) + value + Message.Substring(i+1);
    }
    }
    }

    public int Length
    {
    get
    {
    if(Message!=null)
    {
    return Message.Length;
    }
    else
    return 0;
    }
    }
    }

  3. #13
    معاونت سایت
    تاریخ عضویت
    2012/06/05
    محل سکونت
    Tabriz
    نوشته ها
    14,398

    New 2

    مقدمه ای بر سی شارپ : قسمت چهاردهم
    ارث بری (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();
    }
    }

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

    کد فوق از دو کلاس استفاده می کند. کلاس بالایی ParentClass و کلاس اصلی ChildClass می باشد. کاری که انجام شده است استفاده از کدهای کلاس والد ParentClass در کلاس بچه (!) ChildClass می باشد. برای اینکه ParentClass را بعنوان کلاس پایه برای ChildClass معرفی کنیم به صورت زیر عمل شد :

    public class ChildClass : ParentClass

    کلاس پایه با استفاده از معرفی کولون ":" ، پس از کلاس مشتق شده تعریف می شود. در سی شارپ تنها ارث بری یگانه پشتیبانی می شود. بنابراین تنها یک کلاس پایه را برای ارث بری می توان تعریف کرد.



    ChildClass دقیقا توانایی های ParentClass را دارا است. بنابراین می توان گفت ChildClass همان ParentClass است. برای مثال در کد فوق ChildClass دارای متد print نمی باشد اما آنرا از کلاس ParentClass به ارث برده است و در متد Main برنامه از آن استفاده گردیده است.

    هنگام ساختن یک شیء از کلاس مشتق شده (derived) ، ابتدا یک نمونه از کلاس والد خود بخود ساخته می شود. این مورد در خروجی کد فوق هنگامی که متدهای سازنده ها روی صفحه چاپ شده اند قابل مشاهده است.

    تبادل اطلاعات بین کلاس والد و کلاس فرزند :

    به مثال زیر دقت کنید :

    using System;

    public class Parent
    {
    string parentString;

    public Parent()
    {
    Console.WriteLine("Parent Constructor.");
    }

    public Parent(string myString)
    {
    parentString = myString;
    Console.WriteLine(parentString);
    }

    public void print()
    {
    Console.WriteLine("I'm a Parent Class.");
    }
    }

    public class Child : Parent
    {
    public Child() : base("From Derived")
    {
    Console.WriteLine("Child Constructor.");
    }

    public void print()
    {
    base.print();
    Console.WriteLine("I'm a Child Class.");
    }

    public static void Main()
    {
    Child child = new Child();
    child.print();
    ((Parent)child).print();
    }
    }

    Output:
    From Derived
    Child Constructor.
    I'm a Parent Class.
    I'm a Child Class.
    I'm a Parent Class.

    کلاس فرزند با کلاس والد در هنگام instantiation می تواند تبادل اطلاعات کند. همانطور که در مثال فوق بارز است با استفاده از کلمه ی کلیدی base ، کلاس فرزند تابع سازنده ی کلاس والد را فراخوانی کرده است. اولین خط خروجی بیانگر این موضوع است.

    گاهی از اوقات ما می خواهیم تابعی را که در کلاس والد تعریف شده است را در کلاس فرزند با تعریف دیگری و مخصوص به خودمان ارائه دهیم. در اینصورت تابع تعریف شده در کلاس فرزند ، تابع هم نام والد را مخفی خواهد کرد و دیگر آن تابع والد فراخوانی نخواهد گردید. در این حالت تنها یک راه برای دسترسی به تابع اصلی والد وجود دارد و آن استفاده از base. می باشد که در کد فوق پیاده سازی شده است.
    با استفاده از base. می توان به تمام اعضای public و یا protected کلاس والد از درون کلاس فرزند دسترسی داشت.
    راه دیگری که برای این منظور وجود دارد در آخرین خط کد فوق در متد Main پیاده سازی شده است :

    ((Parent)child).print();

    برای تبدیل نوع های مختلف در سی شارپ می توان از پرانتز و سپس ذکر نوع اصلی استفاده کرد به این عمل casting و یا boxing هم می گویند. در کد فوق درحقیقت child به نوعی از parent تبدیل شده است. بنابراین مانند این است که یک نمونه از کلاس والد متد print همان کلاس را فراخوانی می کند.

  4. #14
    معاونت سایت
    تاریخ عضویت
    2012/06/05
    محل سکونت
    Tabriz
    نوشته ها
    14,398

    New 2

    مقدمه ای بر سی شارپ : قسمت پانزدهم
    پلی مرفیسم (Polymorphism)

    یکی دیگر از مفاهیم اولیه ی شیء گرایی پلی مرفیسم ( چند ریختی ) می باشد. پلی مرفیسم به معنای توانایی استفاده کردن از فرم های مختلف یک نوع است بدون توجه به جزئیات آن .
    برای مثال هنگامیکه سیگنال تلفنی شما فرستاده می شود ، از نوع تلفنی که در انتهای خط موجود است خبری ندارد. تلفن انتهای خط ، می خواهد یکی از تلفن های عهد عتیق باشد و یا تلفنی با آخرین امکانات روز .
    شرکت مخابرات (!) تنها از نوع پایه ای به نام phone خبر دارد و فرض می کند که هر instance از این نوع می داند که چگونه صدای زنگ تلفن شما را به صدا در آورد. بنابراین شرکت مخابرات از تلفن شما به صورت پلی مرف استفاده می کند.
    در عمل پلی مرفیسم هنگامی مفید خواهد بود که بخواهیم گروهی از اشیاء را به یک آرایه نسبت دهیم و سپس متدهای هر یک را فراخوانی کنیم. الزاما این اشیاء از یک نوع نخواهند بود.

    نحوه ی ایجاد متدهای پلی مرفیک :
    برای ایجاد متدی که نیاز است تا پلی مرفیسم را پشتیبانی نماید ، تنها کافی است آنرا از نوع virtual در کلاس پایه تعریف کنیم. مثال :
    فرض کنید تابع DrawWindow در کلاس Window تعریف شده است. برای ایجاد قابلیت پلی مرفیسم در آن به صورت زیر عمل می شود :

    public virtual void DrawWindow( )

    در این حالت هر کلاسی که از Window مشتق شود ، مجاز است نگارش خاص خودش را از DrawWindow ارائه کند. در این صورت در کلاسی که از کلاس پایه ی ما ارث می برد ، تنها کافی است که کلمه ی کلیدی override را قبل از نام تابع مذکور ذکر نماییم.

    یک مثال کامل :

    using System;

    public class DrawingObject
    {
    public virtual void Draw()
    {
    Console.WriteLine("I'm just a generic drawing object.");
    }
    }
    public class Line : DrawingObject
    {
    public override void Draw()
    {
    Console.WriteLine("I'm a Line.");
    }
    }

    public class Circle : DrawingObject
    {
    public override void Draw()
    {
    Console.WriteLine("I'm a Circle.");
    }
    }

    public class Square : DrawingObject
    {
    public override void Draw()
    {
    Console.WriteLine("I'm a Square.");
    }
    }
    public class DrawDemo
    {
    public static int Main(string[] args)
    {
    DrawingObject[] dObj = new DrawingObject[4];

    dObj[0] = new Line();
    dObj[1] = new Circle();
    dObj[2] = new Square();
    dObj[3] = new DrawingObject();

    foreach (DrawingObject drawObj in dObj)
    {
    drawObj.Draw();
    }

    return 0;
    }
    }

    کلاس DrawingObject ، کلاسی پایه برای تمام کد ما که از آن به ارث می برد ، می باشد. متد Draw در آن با کلمه ی کلیدی virtual معرفی شده است. یعنی تمام کلاس های فرزند این کلاس والد می توانند این متد را override کنند ( تحریف کردن و یا تحت الشعاع قرار دادن هم ترجمه شده است! ).
    در ادامه سه کلاس تعریف شده اند که تمامی آنها از کلاس مبنا ارث می برند و تابع Draw را تحریف کرده اند (!). با استفاده از کلمه ی کلیدی override می توان تابع مجازی کلاس مبنا را با تعریفی جدید در زمان اجرای برنامه ارائه داد. تحریف شدن تنها زمانی رخ می دهد که کلاس ، توسط ریفرنس کلاس مبنا مورد ارجاع واقع شده باشد.
    و در متد Main برنامه از این کلاس ها در عمل استفاده گردیده است. در متد Main ، آرایه ای از نوع DrawingObject تعریف و مقدار دهی اولیه شده است تا بتواند 4 شیء از نوع این کلاس را در خودش ذخیره کند.
    بدلیل رابطه ی ارث بری موجود می توان آرایه ی dObj را با نوع هایی از کلاس های Line ، Circle و Square مقدار دهی کرد (همانند کدهای بعدی متد Main ) . اگر ارث بری در اینجا وجود نمی داشت می بایست به ازای هر کلاس یک آرایه تعریف می شد.
    سپس از حلقه ی زیبای foreach برای حرکت در بین اعضای این آرایه استفاده گردیده است. در اینجا هر شیء متد خاص خودش را در مورد Draw فراخوانی می کند و نتیجه را روی صفحه نمایش خواهد داد.
    خروجی نهایی به صورت زیر خواهد بود :

    Output:
    I'm a Line.
    I'm a Circle.
    I'm a Square.
    I'm just a generic drawing object.

  5. #15
    معاونت سایت
    تاریخ عضویت
    2012/06/05
    محل سکونت
    Tabriz
    نوشته ها
    14,398

    New 2

    مقدمه ای بر سی شارپ : قسمت شانزدهم
    کلاس ها ی abstract
    کلاس ها را همچنین می توان به صورت abstract تعریف کرد. از این نوع کلاس ها نمی توان instance ایی را ایجاد نمود. در این کلاس های پایه ، صرفا تعریف متدها و خواص هایی عنوان گردیده و در آینده در کلاس های فرزند توسعه داده خواهند شد. برای مثال :

    public abstract class Named
    {
    public abstract String Name {get; set;} // property
    public abstract void PrintName(); // method
    }
    public class B : Named
    {
    private String name = "empty";
    public override String Name
    {
    get{return name;}
    set{name=value;}
    }
    public override void PrintName()
    {
    Console.WriteLine("Name is {0}", name);
    }
    }

    والی که شاید پیش بیاید این است که اگر interface ها صرفا تعریف توابع و خواص را می توانند در خود جای دهند پس چه دلیلی برای بکار بردن آنها و طولانی کردن کار کد نویسی وجود دارد؟
    کاربردهای زیادی را می توان برای اینترفیس ها برشمرد. اینترفیس یک رفتار را تعریف می کند. فرض کنید در حال توسعه ی برنامه ایی هستید که بر روی دو کامپیوتر مختلف باید با هم در ارتباط مستقیم بوده و برهم کنش داشته باشند و هر برنامه از ماژولی به نام CCommObj communication object استفاده می نماید. یکی از متدهای این شیء ، SendData() می باشد که رشته ای را دریافت کرده و به برنامه ی دیگر می فرستد. این فراخوانی از نوع asynchronous است زیرا ما نمی خواهیم اگر خطایی در شبکه رخ داد، برنامه برای همیشه منتظر باقی بماند. اما چگونه برنامه ی A که تابع ذکر شده را فراخوانی کرده است می تواند تشخیص دهد که پیغام به مقصد رسیده است یا خیر و یا آیا خطایی در شبکه مانع رسیدن پیغام گشته است یا خیر؟ جواب بدین صورت است که CCommObj هنگام دریافت پیغام ، رخدادی را سبب خواهد شد و اگر خطایی رخ داده باشد خیر. در این حالت نیاز به یک ماژول logging نیز احساس می گردد تا خطاهای رخ داده را ثبت نماید. یک روش انجام آن این است که CCommObj پیاده سازی این امکان را نیز بعهده گرفته و اگر فردا نیز خواستیم ماژول دیگری را به برنامه اضافه کنیم هر روز باید CCommObj را تغییر دهیم. تمام این کارها را به سادگی می توان در یک اینترفیس مدل کرد. روش آن نیز در ادامه بیان می گردد:
    در ابتدا یک اینترفیس ایجاد می کنیم تا لیست تمام امکانات ممکن را "منتشر" کند:

    interface ICommObjEvents
    {
    void OnDataSent();
    void OnError();
    }

    شی ء CCommObj ما از این توابع که بعدا توسعه داده خواهند شد برای با خبر سازی کلاینت ها استفاده می نماید. تمام متدها در یک اینترفیس ذاتا پابلیک هستند بنابراین نیازی به ذکر صریح این مطلب نمی باشد و اگر اینکار را انجام دهید کامپایلر خطای زیر را گوشزد خواهد کرد :

    The modifier 'public' is not valid for this item

    در ادامه کلاینت CClientApp_A را پیاده سازی خواهیم کرد :

    class CClientApp_A:ICommObjEvents
    {
    public void OnDataSent()
    {
    Console.WriteLine("OnDataSent");
    }
    public void OnError()
    {
    Console.WriteLine("OnError");
    }
    private CCommObj m_Server;
    public void Init(CCommObj theSource)
    {
    m_Server = theSource;
    theSource.Advise (this);
    string strAdd = ("N450:1");
    m_Server.read (strAdd,10);
    }
    }

    در کد فوق کلاس CClientApp_A از ICommObjEvents ارث برده و تمام متدهای این اینترفیس را پیاده سازی نموده است. هنگامی که CCommObj تابع OnDataSent را فراخوانی می کند این کلاینت پیغام را دریافت خواهد کرد. لازم به ذکر است که کلاس کلاینت ما چون از یک اینترفیس ارث بری می نماید پس باید تمام توابع و خواص کلاس پایه را پیاده سازی کند در غیر اینصورت هر چند برنامه کامپایل خواهد شد اما هنگامی که شیء CCommObj هر کدام از توابع این کلاس را فراخوانی کد ، خطای زمان اجرا رخ خواهد داد.
    متد Init کلاس فوق آرگومانی را از نوع CCommObj دریافت نموده و در یک متغیر private آنرا ذخیره می نماید. همچنین در این متد ، متد Advise از کلاس CCommObj نیز فراخوانی گشته است.

    public class CCommObj
    {
    private int m_nIndex;
    public ICommObjEvents [] m_arSinkColl;
    public CCommObj()
    {
    m_arSinkColl = new ICommObjEvents[10];
    m_nIndex = 0;
    }
    public int Advise(ICommObjEvents theSink)
    {
    m_arSinkColl[m_nIndex] = theSink;
    int lCookie = m_nIndex;
    m_nIndex++;
    return lCookie
    }
    public void SendData(string strData)
    {
    foreach ( ICommObjEvents theSink in m_arSinkColl)
    if(theSink != null )
    theSink.OnDataSent ();
    }
    }

  6. #16
    معاونت سایت
    تاریخ عضویت
    2012/06/05
    محل سکونت
    Tabriz
    نوشته ها
    14,398

    New 2

    مقدمه ای بر سی شارپ : قسمت هفدهم
    در کلاس CCommObj که با آن آشنا شدیم ، آرایه ای Private از نوع ICommObjEvents به نام m_arSinkColl وجود دارد. این آرایه تمام اینترفیس های sink شده را ذخیره می کند. واژه ی sink در اینجا به کلاسی گفته می شود که دریافت کننده ی رخدادها است. متد Advise تنها sink وارده به آنرا در یک آرایه ذخیره می کند و سپس اندیس آرایه را که در اینجا cookie نامیده شده است بر می گرداند. این کوکی توسط کلاینتی که دیگر نمی خواهد از آن آیتم هیچونه رخدادی را دریافت کند به سرور فرستاده می شود و سپس سرور این آیتم را از لیست خودش حذف خواهد کرد.

    نحوه ی فراخوانی متد advise توسط کلاینت نیز جالب است.

    public void Init(CCommObj theSource)
    {
    m_Server = theSource;
    theSource.Advise (this);
    string strAdd = ("Hello");
    m_Server.read (strAdd,10);
    }

    در اینجا تنها یک this بعنوان آرگومان به متد advice فرستاده شده است در حالیکه انتظار می رفت آرگومانی از نوع ICommObjEvents به تابع فرستاده شود. دلیل صحت این عمل بدین صورت است که کلاس ClientApp_A از اینترفیس ICommObjEvents ارث برده است و آنرا پیاده سازی نموده است.
    در ادامه لیست کامل برنامه ی نوشته شده را در حالت Console ملاحظه می فرمایید.

    namespace CSharpCenter
    {

    using System;

    public interface ICommObjEvents
    {
    void OnDataSent();
    void OnError();
    }
    public class CCommObj
    {
    private int m_nIndex;
    public ICommObjEvents [] m_arSinkColl;
    public CCommObj()
    {
    m_arSinkColl = new ICommObjEvents[10];
    m_nIndex = 0;
    }

    public void Advise(ICommObjEvents theSink)
    {

    m_arSinkColl[m_nIndex] = theSink;
    m_nIndex++;
    }
    public void SendData(string strData)
    {
    foreach ( ICommObjEvents theSink in m_arSinkColl)
    {
    if(theSink != null )
    {
    theSink.OnDataSent ();
    }
    }
    }
    }
    class CClientApp_A:ICommObjEvents
    {
    public void OnDataSent()
    {
    Console.WriteLine("OnDataSent Client App A");
    }
    public void OnError()
    {
    Console.WriteLine("OnError");
    }
    public void Read()
    {
    string strAdd = ("Hello");
    m_Server.SendData (strAdd);

    }
    private CCommObj m_Server;
    public void Init(CCommObj theSource)
    {
    m_Server = theSource;
    theSource.Advise (this);
    }
    }
    class CClientApp_B:ICommObjEvents
    {
    public void OnDataSent()
    {
    Console.WriteLine("OnDataSent Client App B");
    }
    public void OnError()
    {
    Console.WriteLine("OnError");
    }
    private CCommObj m_Server;
    public void Init(CCommObj theSource)
    {
    m_Server = theSource;
    theSource.Advise (this);
    }
    }
    class ConsoleApp
    {
    public static void Main()
    {
    CClientApp_A theClient = new CClientApp_A ();
    CClientApp_B theClient2 = new CClientApp_B ();
    CCommObj theComm = new CCommObj ();
    theClient.Init (theComm);
    theClient2.Init (theComm);
    theClient.Read();

    }
    }

    }


    در متد Main برنامه ی فوق ، ما دو کلاینت تعریف کرده ایم و یک نمونه از CCommObj را. دو کلاینت instance های CCommObj را بعنوان آرگومان دریافت کرده اند. در هنگام فراخوانی init توسط هر کلاینت متد advise فراخوانی می گردد. در خاتمه Read مربوط به کلاینت 1 فراخوانی شده است که سبب می شود تا رخداد OnDataSend شیء CCommObj اجرا شود و به تمام کلاینت ها فرستاده شود.

    هدف از این مثال ارائه ی بعضی از جنبه های اینترفیس ها و نحوه ی استفاده از آنها بود. دو مطلب دیگر در مورد اینترفیس ها باقی مانده اند تا به پایان بحث مربوط به آنها برسیم:

    چگونه می توان متوجه شد که یک شیء واقعا یک اینترفیس را پیاده سازی کرده است؟
    دو روش برای فهمیدن این موضوع وجود دارد:
    - استفاده از کلمه ی کلیدی is
    - استفاده از کلمه ی کلیدی as

    اولین مثال زیر از کلمه ی کلیدی is استفاده می کند :

    CClientApp_C theClient3 = new CClientApp_C ();
    if(theClient3 is ICommObjEvents)
    Console.WriteLine ("theClient3 implements ICommObjEvents");
    else
    Console.WriteLine ("theClient3 doesnot implement ICommObjEvents");

    کلمه ی کلیدی is مقدار true را بر می گرداند اگر اپراتور سمت چپ ، اینترفیس سمت راست را پیاده سازی کرده باشد.

    ICommObjEvents theClient5 = theClient3 as ICommObjEvents;
    if(theClient5 != null )
    Console.WriteLine ("Yes theClient implements interface");

    else
    Console.WriteLine ("NO,Yes theClient doesn't implements interface");

    در مثال فوق اپراتور as در حال casting شیء theClient5 به ICommObjEvents می باشد. چون CClientApp_C اینترفیس را پیاده سازی نمی کند حاصل خط اول نال خواهد بود.

    به صورت خلاصه :
    یک اینترفیس قراردادی است که به کلاینت گارانتی می دهد یک کلاس خاص چگونه رفتار خواهد کرد. هنگامیکه کلاسی یک اینترفیس را پیاده سازی می کند به تمام کلاینت ها می گوید که : من تمام موارد ذکر شده در اینترفیس را ارائه و پیاده سازی خواهم کرد. نمونه ی عملی استفاده از اینترفیس ها بحث dot net remoting است.

  7. #17
    معاونت سایت
    تاریخ عضویت
    2012/06/05
    محل سکونت
    Tabriz
    نوشته ها
    14,398

    New 2

    مقدمه ای بر سی شارپ : قسمت هجدهم
    مقابله با خطاها در سی شارپ :
    EXCEPTION یک خطای زمان اجر است که بدلیل شرایطی غیرنرمال در برنامه ایجاد می شود. در سی شارپ exeption کلاسی است در فضای نام سیستم. شیء ایی از نوع exception بیانگر شرایطی است که سبب رخ دادن خطا در کد شده است. سی شارپ از exception ها به صورتی بسیار شبیه به جاوا و سی پلاس پلاس استفاده می نماید.

    دلایلی که باید در برنامه exception handling حتما صورت گیرد به شرح زیر است:
    - قابل صرفنظر کردن نیستند و اگر کدی این موضوع را در نظر نگیرد با یک خطای زمان اجرا خاتمه پیدا خواهد کرد.
    - سبب مشخص شدن خطا در یک نقطه از برنامه شده و ما را به اصلاح آن سوق می دهد.

    بوسیله ی عبارات try...catch می توان مدیریت خطاها را انجام داد. کدی که احتمال دارد خطایی در آن رخ دهد درون try قرار گرفته و سپس بوسیله ی یک یا چند قطعه ی catch می توان آنرا مدیریت کرد. و اگر از این قطعات خطایابی استفاده نشود برنامه به صورتهای زیر متوقف خواهد شد :

    class A {static void Main() {catch {}}}
    TEMP.cs(3,5): error CS1003: Syntax error, 'try' expected

    class A {static void Main() {finally {}}}
    TEMP.cs(3,5): error CS1003: Syntax error, 'try' expected

    class A {static void Main() {try {}}}
    TEMP.cs(6,3): error CS1524: Expected catch or finally

    بهتر است یک مثال ساده را در این زمینه مرور کنیم:

    int a, b = 0 ;
    Console.WriteLine( "My program starts " ) ;
    try
    {
    a = 10 / b;
    }
    catch ( Exception e )
    {
    Console.WriteLine ( e ) ;
    }
    Console.WriteLine ( "Remaining program" ) ;
    The output of the program is:
    My program starts
    System.DivideByZeroException: Attempted to divide by zero.
    at ConsoleApplication4.Class1.Main(String[] args) in
    d:dont deleteconsoleapplication4class1.cs:line 51
    Remaining program


    برنامه شروع به اجرا می کند. سپس وارد بلوک و یا قطعه ی try می گردد. اگر هیچ خطایی هنگام اجرای دستورات داخل آن رخ ندهد ، برنامه به خط آخر جهش خواهد کرد و کاری به قطعات catch ندارد.
    اما در اینجا در اولین try عددی بر صفر تقسیم شده است بنابراین کنترل برنامه به بلوک catch منتقل می شود و صرفا نوع خطای رخ داده شده نوشته و نمایش داده می شود. سپس برنامه به کار عادی خودش ادامه می دهد.

    تعدادی از کلاس های exception در سی شارپ که از کلاس System.Exception ارث برده اند به شرح زیر هستند :

    • Exception Class - - Cause
    • SystemException - A failed run-time check;used as a base class for other.
    • AccessException - Failure to access a type member, such as a method or field.
    • ArgumentException - An argument to a method was invalid.
    • ArgumentNullException - A null argument was passed to a method that doesn't accept it.
    • ArgumentOutOfRangeException - Argument value is out of range.
    • ArithmeticException - Arithmetic over - or underflow has occurred.
    • ArrayTypeMismatchException - Attempt to store the wrong type of object in an array.
    • BadImageFormatException - Image is in the wrong format.
    • CoreException - Base class for exceptions thrown by the runtime.
    • DivideByZeroException - An attempt was made to divide by zero.
    • FormatException - The format of an argument is wrong.
    • IndexOutOfRangeException - An array index is out of bounds.
    • InvalidCastExpression - An attempt was made to cast to an invalid class.
    • InvalidOperationException - A method was called at an invalid time.
    • MissingMemberException - An invalid version of a DLL was accessed.
    • NotFiniteNumberException - A number is not valid.
    • NotSupportedException - Indicates sthat a method is not implemented by a class.
    • NullReferenceException - Attempt to use an unassigned reference.
    • OutOfMemoryException - Not enough memory to continue execution.
    • StackOverflowException - A stack has overflown.

    در کد فوق صرفا عمومی ترین نوع از این کلاس ها که شامل تمامی این موارد می شود مورد استفاده قرار گرفت یعنی :

    catch ( Exception e )

    اگر نیازی به خطایابی دقیقتر باشد می توان از کلاس های فوق برای اهداف مورد نظر استفاده نمود.

    مثالی دیگر: ( در این مثال خطایابی دقیق تر با استفاده از کلاس های فوق و همچنین مفهوم finally نیز گنجانده شده است )

    int a, b = 0 ;
    Console.WriteLine( "My program starts" ) ;
    try
    {
    a = 10 / b;
    }
    catch ( InvalidOperationException e )
    {
    Console.WriteLine ( e ) ;
    }
    catch ( DivideByZeroException e)
    {
    Console.WriteLine ( e ) ;
    }
    finally
    {
    Console.WriteLine ( "finally" ) ;
    }
    Console.WriteLine ( "Remaining program" ) ;
    The output here is:
    My program starts
    System.DivideByZeroException: Attempted to divide by zero.
    at ConsoleApplication4.Class1.Main(String[] args) in
    d:dont deleteconsoleapplication4class1.cs:line 51
    finally
    Remaining program

    قسمت موجود در قطعه ی فاینالی همواره صرفنظر از قسمت های دیگر اجرا می شود.

    به مثال زیر دقت کنید :

    int a, b = 0 ;
    Console.WriteLine( "My program starts" )
    try
    {
    a = 10 / b;
    }
    finally
    {
    Console.WriteLine ( "finally" ) ;
    }
    Console.WriteLine ( "Remaining program" ) ;
    Here the output is
    My program starts
    Exception occurred: System.DivideByZeroException:
    Attempted to divide by zero.at ConsoleApplication4.Class1.
    Main(String[] args) in d:dont deleteconsoleapplication4
    class1.cs:line 51
    finally

    قسمت چاپ Remaining program اجرا نشده است.

    عبارت throw :

    این عبارت سبب ایجاد یک خطا در برنامه می شود.

    مثال :

    int a, b = 0 ;
    Console.WriteLine( "My program starts" ) ;
    try
    {
    a = 10 / b;
    }
    catch ( Exception e)
    {
    throw
    }
    finally
    {
    Console.WriteLine ( "finally" ) ;
    }

    در این حالت قسمت فاینالی اجرا شده و برنامه بلافاصله خاتمه پیدا می کند.

  8. #18
    معاونت سایت
    تاریخ عضویت
    2012/06/05
    محل سکونت
    Tabriz
    نوشته ها
    14,398

    New 2

    مقدمه ای بر سی شارپ : قسمت نوزدهم
    سربارگذاری عملگر ها (Operator OverLoading):

    به تعریف مجدد راه و روش اجرای عملگر ها توسط ما ، سربارگذاری عملگرها گفته می شود. فرض کنید می خواهید عدد 2 را به یک مقدار datetime اضافه کنید. خطای زیر حاصل خواهد شد:

    CS0019: Operator '+' cannot be applied to operands of type 'System.DateTime' and 'int'


    جالب بود اگر می توانستیم عدد 2 را به datetime اضافه کنیم و نتیجه ی آن تعداد روزهای مشخص بعلاوه ی دو می بود. اینگونه توانایی ها را می توان بوسیله ی operator overloading ایجاد کرد.

    تنها عملگر های زیر را می توان overload کرد:

    Unary Operators
    + - ! ~ ++ -- true false

    Binary Operators
    + - * / % & | ^ << >> == != > < >= <=


    نحوه ی انجام اینکار نیز در حالت کلی به صورت زیر است:

    return_datatype operator operator_to_be_overloaded (agruments)
    {
    }


    به مثال زیر توجه کنید:

    using System;
    class MyDate
    {
    public DateTime tempDate;
    public MyDate(int year,int month,int day)
    {
    tempDate=new DateTime(year,month,day);
    }
    public static DateTime operator + (MyDate D,int noOfDays)
    {
    return D.tempDate.AddDays(noOfDays);
    }
    public static DateTime operator + (int noOfDays,MyDate D)
    {
    return D.tempDate.AddDays(noOfDays);
    }
    }

    class Test
    {
    static void Main()
    {
    MyDate MD=new MyDate(2001,7,16);
    Console.WriteLine(MD + 10 );
    }
    }

    output:
    2001-07-26

    در مثال فوق عملگر + دوبار overload شده است. یکبار توسط آن می توان یک عدد صحیح را به یک تاریخ اضافه کرد و بار دیگر یک یک تاریخ را می توان به عدد صحیح افزود.


    موارد زیر را هنگام سربارگذاری عملگرها به خاطر داشته باشید:

    1- تنها اپراتورهای ذکر شده را می توان overload کرد. اپراتورهایی مانند new,typeof, sizeof و غیره را نمی توان سربارگذاری نمود.
    2- خروجی متدهای بکار گرفته شده در سربارگذاری عملگر ها نمی تواند void باشد.
    3- حداقل یکی از آرگومانهای بکار گرفته شده در متدی که برای overloading عملگرها بکار می رود باید از نوع کلاس حاوی متد باشد.
    4- متدهای مربوطه باید به صورت public و static تعریف شوند.
    5- هنگامی که اپراتور < را سربارگذاری می کنید باید جفت متناظر آن یعنی > را هم سربارگذاری نمایید.
    6- هنگامیکه برای مثال + را overload می کنید خودبخود =+ نیز overload شده است و نیازی به کدنویسی برای آن نیست.


    یکی از موارد جالب بکار گیری سربارگذاری عملگرها در برنامه نویسی سه بعدی و ساختن کلاسی برای انجام عملیات ماتریسی و برداری می باشد.

  9. #19
    معاونت سایت
    تاریخ عضویت
    2012/06/05
    محل سکونت
    Tabriz
    نوشته ها
    14,398

    New 2

    مقدمه ای بر سی شارپ : قسمت بیستم
    Delegates
    Delegates در سی شارپ روشی مطمئن و typesafe را برای بکار گیری مفهوم function pointer ارائه می دهند. یکی از ابتدایی ترین استفاده های function pointers پیاده سازی callback می باشد. اما در ابتدا لازم است تا با اصول اولیه ی کاری آن آشنا شویم.

    مثال یک :
    یک delegate چگونه تعریف و استفاده می شود؟
    Delegate یک شیء است که بیانگر یک تابع می باشد بنابراین می تواند بعنوان آرگومان ورودی یک تابع دیگر و یا عضوی از یک کلاس بکار رود.
    در زبان "function-pointer" ، Func1() اشاره گری به Func2() را بعنوان پارامتر دریافت کرده و نهایتا آنرا فراخوانی می کند.
    در زبان "delegate" ، Func1() یک شیء delegate از Func2() را دریافت کرده و سپس آنرا فراخوانی می کند.
    در مثال زیر از دو تابع برای شرح این مطلب سود جسته شده است:
    Func1() از delegate استفاده می کند.
    Func2() یک delegate است.

    ( شماره گذاری خطوط ، در کد زیر ، صرفا برای راحت تر شدن توضیحات در مورد آنها است و لزومی به تایپ آنها در برنامه ی اصلی نیست. )

    01 using System;
    02 delegate void Delg(string sTry);
    03 public class Example1{

    // function which uses the delegate object
    04 private static void Func1(Delg d){
    05 d("Passed from Func1");
    06 }

    // function which is passed as an object
    07 private static void Func2(string sToPrint){
    08 Console.WriteLine("{0}",sToPrint);
    09 }

    // Main execution starts here
    10 public static void Main(){
    11 Delg d = new Delg(Func2);
    12 Func1(d);
    13 }
    14 }

    LINE 02
    یک شیء delegate را برای Func2 تعریف می کند.

    LINE 04-06
    تابعی را تعریف کرده است که آرگومان ورودی آن از نوع Delg است.

    LINE 07-09
    تابعی را تعریف می کند که باید به صورت delegate به تابع دیگر فرستاده شود.

    LINE 10-14
    تابع Main اجرای برنامه را با ایجاد یک شیء delegate برای Func2 آغاز کرده و سپس تابع Func1 را فراخوانی می کند.


    مثال 2:
    چگونه می توان از delegates در کارهای عملی استفاده کرد؟

    طرح یک مساله:
    شخصی تقاضای ثبت نام در یک مؤسسه ی آموزشی و همچنین تقاضای کاریابی در یک شرکت را داده است. هر کدام از این نهادها روشی خاص خود را برای ارزیابی شخص دارند.

    راه حل (با روشی شیء گرا):
    شخص مشخصاتی همچون سن / جنس / میزان تحصیلات قبلی / تجربیات کاری و مدارک مرتبط دارد.
    مؤسسه ی آموزشی تعدادی از این مشخصات را برای ارزیابی شخص استفاده می کند و این امر در مورد شرکت یاد شده نیز صادق است.
    شیء شرکت و شیء آموزشگاه هر کدام توابع ارزیابی خاص خودشان را پیاده سازی می کنند.
    شخص ، اینترفیسی واحدی را در اختیار شرکت / آموزشگاه برای ارزیابی خود قرار می دهد.

    پیاده سازی (با استفاده از سی شارپ):
    ما delegate‌ایی را تعریف می کنیم که بیانگر اینترفیسی است که به شرکت و آموزشگاه اجازه ی چک کردن شخص را می دهد.
    سه کلاس school و company و person را تعریف می نماییم.
    کلاس test را برای آزمودن این موارد ایجاد می کنیم.

    01 using System;
    02 using System.Collections;

    03 public delegate bool GetChecker(Person p);

    // Person has his information with him as he
    // applies for School and Company
    04 public class Person
    05 {
    06 public string Name;
    07 public int Age;
    08 public bool Graduate;
    09 public int YearsOfExp;
    10 public bool Certified;

    11 public Person(string name,
    int age,
    bool graduate,
    int yearsOfExp,
    bool certified)
    12 {
    13 Name=name;
    14 Age=age;
    15 Graduate=graduate;
    16 YearsOfExp=yearsOfExp;
    17 Certified=certified;
    18 }
    19 public bool CheckMe(GetChecker checker)
    20 {
    21 return(checker(this));
    22 }
    23 }

    // A school, the person applied for higher studies
    24 public class School
    25 {
    26 public static bool SchoolCheck(Person p)
    27 {
    28 return (p.Age>10 && p.Graduate);
    29 }
    30 }

    // A Company, the person wants to work for
    31 public class Company
    32 {
    33 public static bool CompanyCheck(Person p)
    34 {
    35 return (p.YearsOfExp>5 && p.Certified);
    36 }
    37 }

    // A Test class, displays delegation in action
    38 public class Test
    39 {
    40 public static void Main()
    41 {
    42 Person p1 = new Person("Jack",20,true,6,false);
    43 Console.WriteLine("{0} School Check : {1}",
    p1.Name,
    p1.CheckMe(new GetChecker(School.SchoolCheck)));
    44 Console.WriteLine("{0} Company Check : {1}",
    p1.Name,
    p1.CheckMe(new GetChecker(Company.CompanyCheck)));
    45 }
    46 }

    LINE 03
    Delegate مورد نیاز را تعریف می کند.

    LINE 04-23
    کلاس person را تعریف می کند. این کلاس تابعی پابلیک را ارائه می دهد که آرگومان ورودی آن از نوع GetChecker می باشد.

    LINE 24-30
    کلاس school را تعریف می کند و سپس تابعی را که delegate است ارائه می دهد.

    LINE 31-37
    کلاس company را تعریف می کند و سپس تابعی را که delegate است ارائه می دهد.

    LINE 38-36
    کلاس test را پیاده سازی می نماید. سپس یک شیء شخص ساخته می شود. در ادامه new GetChecker(School.SchoolCheck) و new GetChecker(Company.CompanyCheck) شیء ایی را ایجاد می کند از نوع delegate مورد نیاز و آنرا به تابع CheckMe می فرستد. خروجی نتیجه ی ارزیابی این شخص می باشد.

    اگر چک کردن اشخاص بیشتری نیاز باشد به این صورت عمل می شود:

    Person p1 = new Person("Jack",20,true,6,false);
    Person p2 = new Person("Daniel",25,true,10,true);
    GetChecker checker1= new GetChecker(School.SchoolCheck);
    GetChecker checker2= new GetChecker(School.CompanyCheck);

    Console.WriteLine("{0} School Check : {1}",
    p1.Name,p1.CheckMe(checker1));
    Console.WriteLine("{0} Company Check : {1}",
    p1.Name,p1.CheckMe(checker2));
    Console.WriteLine("{0} School Check : {1}",
    p2.Name,p2.CheckMe(checker1));
    Console.WriteLine("{0} Company Check : {1}",
    p2.Name,p2.CheckMe(checker2));

    مثال 3 :
    Delegates در تعامل بین دات نت فریم ورک و سی شارپ چه نقشی دارد؟

    طرح یک مساله:
    نمایش دادن میزان پیشرفت خواندن یک فایل هنگامی که حجم فایل بسیار زیاد است.

    راه حل ( با استفاده از سی شارپ):
    در مثال زیر از کلاس FileReader برای خواندن یک فایل حجیم استفاده شده است. هنگامیکه برنامه مشغول خواندن فایل است 'Still reading.. را نمایش می دهد و در پایان 'Finished reading..'. را عرضه می کند.
    برای اینکار از فضای نام System.IO استفاده شده است. این فضای نام حاوی delegate ایی مهیا شده برای ما می باشد. بدین ترتیب می توانیم به دات نت فریم ورک بگوییم که ما تابعی را تعریف کرده ایم که او می تواند آنرا فراخوانی کند.
    سؤال: چه نیازی وجود دارد تا دات نت فریم ورک تابع ما را فراخوانی و اجرا کند؟ با استفاده از تابع ما که دات نت فریم آنرا صدا خواهد زد در طول خواندن فایل به ما گفته می شود که بله! من هنوز مشغول خواندن هستم! به این عملیات Callback نیز گفته می شود. به اینکار پردازش asynchronous نیز می گویند!

    01 using System;
    02 using System.IO;

    03 public class FileReader{
    04 private Stream sInput;
    05 private byte[] arrByte;
    06 private AsyncCallback callbackOnFinish;

    07 public FileReader(){
    08 arrByte=new byte[256];
    09 callbackOnFinish = new AsyncCallback(this.readFinished);
    10 }

    11 public void readFinished(IAsyncResult result){

    12 if(sInput.EndRead(result)>0){
    13 sInput.BeginRead(arrByte,
    0,
    arrByte.Length,
    callbackOnFinish,
    null);
    14 Console.WriteLine("Still reading..");
    15 }
    16 else Console.WriteLine("Finished reading..");
    17 }

    18 public void readFile(){
    19 sInput = File.OpenRead(@"C:big.dat");
    20 sInput.BeginRead(arrByte,
    0,
    arrByte.Length,
    callbackOnFinish,
    null);
    21 for(long i=0;i<=1000000000;i++){
    // just to introduce some delay
    22 }
    23 }

    24 public static void Main(){
    25 FileReader asynctest=new FileReader();
    26 asynctest.readFile();
    27 }
    28 }

    LINE 02
    فضای نام System.IO را به برنامه ملحق می کند. این فضای نام به صورت خودکار حاوی تعریف delegate زیر می باشد:

    public delegate void AsyncCallback (IAsyncResult ar);

    LINE 03-10
    تعریف کلاس

    LINE 06
    شیء delegate را تعریف می کند.

    LINE 07-10
    سازنده ی کلاس را پیاده سازی می کنند. در اینجا ما تصمیم گرفته ایم که بافری حاوی 256 بایت را در هر لحظه بخوانیم.

    LINE 09
    شیء delegate نمونه سازی شده است.

    LINE 18-23
    readFile را پیاده سازی می کند.

    LINE 12-16
    نحوه ی استفاده از شیء IAsyncResult را بیان می کند.

    LINE 12
    sInput.EndRead(result) تعداد بایتهای خوانده شده را بر می گرداند. این خواندن تاجایی که تعداد بایتهای خوانده شده صفر است ادامه پیدا می کند و در اینجا 'Finished reading' اعلام می گردد.

صفحه 2 از 2 نخستنخست 12

کلمات کلیدی این موضوع

مجوز های ارسال و ویرایش

  • شما نمیتوانید موضوع جدیدی ارسال کنید
  • شما امکان ارسال پاسخ را ندارید
  • شما نمیتوانید فایل پیوست کنید.
  • شما نمیتوانید پست های خود را ویرایش کنید
  •