واسطها (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 هاي تودرتو را نشان مي‌دهد.

ادامه نوشته