ورود کاربران VIP سرزمین دانلود، مرجع دانلود و آموزش رایگان نرم افزار

منوی سایت

آموزش پیشرفته سی شارپ

تازه های این بخش :

مقدمه ای بر سی شارپ : قسمت بیستم

(مربوط به موضوع آموزش پیشرفته سی شارپ)

مقدمه ای بر سی شارپ : قسمت بیستم


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' اعلام می گردد.

 

سایر مقالات مرتبط با این موضوع

 


این مطلب مربوط به موضوع آموزش پیشرفته سی شارپ میباشد.

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

(مربوط به موضوع آموزش پیشرفته سی شارپ)

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


سربارگذاری عملگر ها (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 شده است و نیازی به کدنویسی برای آن نیست.


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

 

سایر مقالات مرتبط با این موضوع

 


این مطلب مربوط به موضوع آموزش پیشرفته سی شارپ میباشد.

مقدمه ای بر سی شارپ : قسمت هجدهم

(مربوط به موضوع آموزش پیشرفته سی شارپ)

مقدمه ای بر سی شارپ : قسمت هجدهم


مقابله با خطاها در سی شارپ :
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" ) ;
}


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

 

سایر مقالات مرتبط با این موضوع

 

 


این مطلب مربوط به موضوع آموزش پیشرفته سی شارپ میباشد.
سرزمین دانلود، مرجع دانلود و آموزش نرم افزار

سرزمین دانلود را دنبال کنید !

عضویت در خبرنامه سرزمین دانلود

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



------------------------------------------