upload کردن فایل به سرور در ASP.NET |
![]() |
Namespace چیست؟ |
![]() |
Smart Navigation چیست؟ |
![]() |
چرا به دات نت احتیاج داریم؟ |
![]() |
نشان دادن قابلیتهای مرورگر در ASP.NET |
![]() |
آشنائی با ASP.NET |
![]() |
نحوه پردازش صفحات ASP.NET بر روی سرویس دهنده وب |
![]() |
ارسال ایمیل در ASP.NET با استفاده از HTML Template |
![]() |
اضافه کردن تصویر به پایگاه داده |
![]() |
برسی کوکیها (Cookies) و جلسات (Sessions) در ASP.NET |
![]() |
باز کردن پنجره Popup در ASP.NET با استفاده از Code Behind |
![]() |
آشنائی با فرمهای وب در ASP.NET |
![]() |
درس هفدهم : انواع شمارشی در 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 در حالت کلی بصورت زیر است :
{
// 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 صورت گرفته و سپس به دنبال آن نام این مجموعه مشخص میشود. درون کروشههای باز و بسته { } نیز، عناصر نوع شمارشی اعلان میگردند.
نوع شمارشی تولید شده در این مثال از نوع Volume است و در متد Main() از آن برای اعلان myVolume استفاده شده است. از آنجائیکه enum یک نوع مقداری است، میتوانیم بطور مستقیم آنرا مقداردهی نماییم. پس از آنکه متغیر myVolume مقداردهی شد، میتوان همانند سایر انواع مقداری، مانند int، از آن استفاده نمود. در حلقه switch، متغیر myVolume با عناصر enum مقایسه میشوند.
در هربار استفاده از عناصر enum تولید شده، از نام enum تولید شده، در اینجا Volume، در ابتدای نام عنصر استفاده مینماییم (Volume.Medium)، زیرا در صورتیکه در یک برنامه چندین enum وجود داشته باشند که دارای عناصری با نامهای یکسان باشند، در صورت عدم استفاده از نام enum مورد نظر قبل از عنصر، ابهام بوجود آمده و دچار مشکل میشویم.
بطور پیش فرض، به اولین عنصر تعریف شده در enum مقدار صفر تخصیص داده میشود که این مقدار تنها بعنوان اندیسی جهت دسترسی به این عنصر در نظر گرفته میشود. سایر عناصر enum نیز بطور صعودی مقدار میگیرند و به هر عنصر یک واحد افزوده میشود. در مثال 1-17، عنصر Low دارای اندیس صفر بوده و سایر عناصر به ترتیب مقدار 1 و 2 خواهند داشت.
در C#، برای موارد خاص میتوان مقادیر پیش فرض در نظر گرفته شده برای عناصر enum را تغییر داد. به مثال زیر توجه کنید.
enum Months
{
jan, feb, mar, apr
}
enum Months
{
jan = 10, feb = 20, mar = 30, apr=40
}
همنطور که مشاهده میشود، در اعلان اول، از مقدار پیش فرض استفاده شده، که در این حالت jan = 0، feb = 1، mar = 2 و apr = 3 خواهند بود. اما در اعلان دوم، برنامهنویس بنا به نیاز خود، تشخیص داده تا به هر یک از عناصر enum مقداری دلخواه را نسبت دهد.
هر چند به تمامی عناصر enum مقداری نسبت داده میشود ولی از این مقدار نمیتوان بطور مسقیم در تخصیص دهی مقدار به متغیری دیگر استفاده نمود. به مثال زیر توجه نمایید :
int x = Months.jan;// این دستور نادرست است
int x = (int) Months.jan ; //صحیح
برای استفاده از مقدار تخصیص داده شده به عناصر enum، باید از Casting استفاده نماییم. بدین معنا که باید نوع متغییری را که میخواهیم مقدار را به ان نسبت دهیم، باید مشخص شود. در مثال فوق (int) Months.jan معین میکند که مقدار تخصیص داده شده به jan به متغییری نسبت داده میشود که از نوع int است و یا به عبارت صحیح تر، مقدار تخصیص داده شده به عنصر enum، در فرمت int به متغییر مورد نظر تخصیص داده میشود.
در ادامه مبحث، توجه شما را به مثالی دیگر درباره enum جلب می نمایم. توجه نمایید که نکات جدیدی نیز در این مثال گنجانده شده اند.
مثال 2-17 : ساخت enum پایه و تخصیص دهی اعضای آن
using System;
// declares the enum
public enum Volume : byte
{
Low = 1,
Medium,
High
}
class EnumBaseAndMembers
{
static void Main()
{
// create and initialize
// instance of enum type
Volume myVolume = Volume.Low;
// 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();
}
}
با توجه به مثال 2-17 با نحوه تغییر نوع پایه یک enum آشنا می شوید. همانطور که ملاحظه می نمایید، نوع پایه این enum به byte تغییر یافته است. این امر بیان میدارئ که تنها مقادیری از نوع byte قابل تخصیص به عناصر enum هستند.
همانطور که قبلا نیز اشاره شد، مقدار پیش فرض برای اولین عضو enum یعنی Low برابر با صفر است. چون در این مثال مقدار Low را برابر با یک قرار داده ایم، از اینرو مقادیر دو عضو دیگر آن نیز بصورت Middle=2 و High=3 تغییر خواهند یافت.
نکات پیشرفته درباره enum
در زبان C# هر نمونه از enum فضایی معادل با 4 بایت از حافظه را اشغال می نمایند. این مطلب با استفاده از کلمه کلیدی sizeof قابل بررسی لسا. از اینرو از enum میتوان به عنوان یک ساختمان داده مناسب و کارا یاد کرد.
نکته بسیار مهم و جالب در مورد enum در زبان برنامه نویسی C# انست که، برای هر کلاس enum موجود در کد برنامه، مقادیر رشته ای تخصیص داده شده به عناصر enum در یک اسمبلی و بصورت Metadata ذخیره می گردند، از اینرو دسترسی به این مقادیر رشته ای در کد میسر می شود. همچنین می توان از متدهای مختلف مرتبط با enum نیز استفاده نمود. به مثال ساده زیر توجه نمایید :
enum Language
{
CSharp,MCpp,VBNet,JScript,IL
}
class App
{
public static void Main()
{
Console.WriteLine("Write the number of the selected Language");
string[] langAr = Enum.GetNames(Type.GetType("Language"));
for(int i=0;i
{
Console.WriteLine(i + "." + langAr[i]);
}
Language myLang=(Language)Convert.ToInt32(Console.ReadLine());
Console.WriteLine("Your Language of choice is: " + myLang);
}
}
C# Tutorial For Beginners
Author : Joe Mayo
Copyrights © 2001-2003
http://www.csharp-station.com/
Enums Powered By Reflection
Author : JSLA
Copyrights © 2003 Jose Luis Sampayo Aller
Copyrights © 2003 The Code Project
Enumerators in C#
Author : Rajesh V. S.
Copyrights © 2001 Rajesh V. S.
Copyrights © 2001 C# Corner
ادامه درس شانزدهم
تعریف و یا کنترل موارد استفاده از یک صفت
AttributeUsage یکی از کلاسهای از پیش تعریف شده در زبان است که با استفاده از آن میتوانیم موارد استفاده از صفتی را که تولید کردهایم را کنترل کنیم.
این کلاس دارای سه property مختلف است که میتوان آنها را به هنگام استفاده صفت شخصی تنظیم نمود و مورد استفاده قرار داد.
ValidOn
با استفاده از این property میتوانیم مشخص کنیم که صفت تولید شده توسط ما، بر روی کدام یک از عناصر برنامه قابل اعمال هستند. اطلاعات این عناصر از AttributeTarget گرفته میشود و میتوان عناصر مختلف را بوسیله OR بیتی با یکدیگر ترکیب نمود.
AllowMultiple
با استفاده از این property میتوان مشخص کرد که آیا میتوان از این صفت بیش از یکبار بر روی یک عنصر برنامه استفاده کرد یا نه.
Inherited
با استفاده از این property میتوان قوانین ارثبری این صفت را کنترل نمود. با استفاده از این property میتوان مشخص کرد که آیا کلاسی که از کلاسی که صفت بر روی آن اعمال شده، ارث بری میکند نیز، صفت بر رویش اعمال میشود یا نه و یا به عبارتی صفت در کلاس مشتق شده نیز مورد ارثبری قرار میگیرد یا نه.
حال با استفاده از موارد گفته شده در بالا، میخواهیم این مطالب را بر روی صفتی که خودمان تولید کردیم اعمال نماییم. مثال 7-16 را بررسی نمایید.
مثال 7-16
using System;
[AttributeUsage(AttributeTargets.Class), AllowMultiple = false, Inherited = false ]
public class HelpAttribute : Attribute
{
public HelpAttribute(String Description_in)
{
this.description = Description_in;
}
protected String description;
public String Description
{
get
{
return this.description;
}
}
}
در ابتدا به AttributeTargets.Class توجه نمایید. این مشخص میکند که صفت Help تنها بر روی کلاسها قابل اعمال است و در صورتیکه از آن بر روی عنصری به غیر از کلاس استفاده نماییم خطایی رخ خواهد داد. بنابراین کد زیر، خطایی تولید خواهد کرد :
[Help("this is a do-nothing class")]
public class AnyClass
{
[Help("this is a do-nothing method")] //error
public void AnyMethod()
{
}
}
و کد خطای تولید شده بشکل زیر خواهد بود :
AnyClass.cs: Attribute 'Help' is not valid on this declaration type.
It is valid on 'class' declarations only.
توجه کنید که با استفاده از AttributeTargets.All به صفت Help این امکان را میدهیم تا بر روی تمامی عناصر موجود اعمال شود. لیست کامل عناصر مجاز نیز بشرح زیر است :
حال به AllowMultiple = false توجه نمایید. با استفاده از این کد، به صفت Help اجازه میدهیم تا تنها یکبار بر روی عنصری از برنامه اعمال شود. پس کد زیر تولید خطا مینماید :
[Help("this is a do-nothing class")]
[Help("it contains a do-nothing method")]
public class AnyClass
{
[Help("this is a do-nothing method")] //error
public void AnyMethod()
{
}
}
و کد خطای تولید شده نیز بصورت زیر است :
AnyClass.cs: Duplicate 'Help' attribute
در نهایت نیز به بررسی Inherited میپردازیم. با استفاده از این ویژگی، معین میکنیم درصورتیکه کلاس دیگری بخواهد از روی کلاسی که صفت بر روی آن اعمال شده ارثبری نماید، آیا این صفت بر روی آن کلاس نیز اعمال شود یا نه. در صورتیکه مقدار این ویژگی برابر با True باشد، کلاس مشتق شده نیز از صفت ارثبری مینماید. برای یک مثال میتوانیم حالت زیر را در نظر بگیریم :
[Help("BaseClass")]
public class Base
{
}
public class Derive : Base
{
}
تمامی حالتهای مختلف ترکیب این سه ویژگی بصورت زیر است :
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false ]
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = false ]
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = true ]
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true, Inherited = true ]
استفاده از پارامترهای Positional و Named در صفتهای شخصی
همانطور که در قبل نیز اشاره شد، پارامترهای Positional پارامترهای سازنده صفت هستند و در هر بار استفاده از صفت باید لحاظ شوند. حال برای بررسی میخواهیم پارامترهایی به صفت Help خود اضافه نماییم.
مثال 8-16
[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
public class HelpAttribute : Attribute
{
public HelpAttribute(String Description_in)
{
this.description = Description_in;
this.verion = "No Version is defined for this class";
}
protected String description;
public String Description
{
get
{
return this.description;
}
}
protected String version;
public String Version
{
get
{
return this.version;
}
//if we ever want our attribute user to set this property,
//we must specify set method for it
set
{
this.verion = value;
}
}
}
[Help("This is Class1")]
public class Class1
{
}
[Help("This is Class2", Version = "1.0")]
public class Class2
{
}
[Help("This is Class3", Version = "2.0", Description = "This is do-nothing class")]
public class Class3
{
}
پس از اینکه این صفت را بر روی کلاس Class1 اعمال کردیم و بخواهیم آنرا کامپایل کنیم با پیغام زیر روبرو میشویم :
Help.Description : This is Class1
Help.Version :No Version is defined for this class
چون در اینجا هیچ مقداری برای Version در نظر نگرفتهایم، با این پیام مواجه شدهایم.
حال نتیجه اعمال این صفت را بر روی کلاس دوم بررسی میکنیم.
Help.Description : This is Class2
Help.Version : 1.0
برای پارامترهای اختیاری معمولا از دو سازنده استفاده نمیشود و در عوض از پارامترهای Named استفاده میگردد. نکتهای که باید به آن توجه کنید آنست که برای پارامترهای Named حتما باید در تعریف property، از متد set نیز استفاده نمایید در غیر اینصورت با پیغام خطای زیر روبرو میشوید :
'Version' : Named attribute argument can't be a read only property
بنابراین درصورتیکه این صفت را بر روی کلاس سوم نیز اعمال کنیم با پیغام خطای مشابهی روبرو خواهیم شد. اگر در کلاس Help تغییری کوچکی اییجاد کنیم و به Description نیز متد set را بیفزاییم، با خطا مواجه نخواهیم شد.
Help.Description : This is do-nothing class
Help.Version : 2.0
اتفاقی که در اینجا رخ میدهد آنست که در ابتدا سازنده (Constructor) این صفت به همراه پارامترهای Positional آن فراخوانده میشوند و سپس متد set برای هر یک از پارامترهای Named فراخوانده میشود .
انواع (type) معتبر برای پارامترهای صفت
انواع معتبر برای پارامترهای صفت بشرح زیر میباشند :
bool,byte,char,double,float,int,long,short,string,System.Type ,object
همچنین میتوان از enum و یا آرایهای تک بعدی، که عناصر آن یکی از انواع فوق باشد، نیز استفاده نمود.
استفاده از صفتها در زمان اجرا
تا کنون با طریقه ساخت صفتها و چگونگی استفاده و اعمال آنها بر عناصر مختلف برنامه آشنا شدیم. حال نوبت به آن رسیده است تا ببینیم چگونه میتوان از صفتها در زمان اجرا استفاده نمود. برای جستجوی (query) یک برنامه درباره صفت موجود در آن، به Reflection نیازمندیم. Reflection قابلیت بدست آوردن اطلاعات مربوط به انواع (Types) مختلف در زمان اجرای برنامه است. با استفاده از توابع Reflection موجود در .Net Framework میتوانیم با جستجو و پیمایش Metadate مربوط به یک اسمبلی، لیست کاملی از کلاسها، انواع و متدهایی را که برای آن اسمبلی خاص تعریف شدهاند را، بدست آوریم. به مثال 9-16 در این باره توجه نمایید.
مثال 9-16 : استفاده از Reflection
using System;
using System.Reflection;
using System.Diagnostics;
//attaching Help attribute to entire assembly
[assembly : Help("This Assembly demonstrates custom attributes creation and their run-time query.")]
//our custom attribute class
public class HelpAttribute : Attribute
{
public HelpAttribute(String Description_in)
{
//
// TODO: Add constructor logic here
this.description = Description_in;
//
}
protected String description;
public String Description
{
get
{
return this.deescription;
}
}
}
//attaching Help attribute to our AnyClass
[HelpString("This is a do-nothing Class.")]
public class AnyClass
{
//attaching Help attribute to our AnyMethod
[Help("This is a do-nothing Method.")]
public void AnyMethod()
{
}
//attaching Help attribute to our AnyInt Field
[Help("This is any Integer.")]
public int AnyInt;
}
class QueryApp
{
public static void Main()
{
}
}
مبحث صفتها بسیار گسترده است و میتوان ساعتها در مورد صفتهای مختلف بحث نمود. اما آنچه مسلم است تمرین مستمر و پیگیری برنامه نویس در یافتن مواردی که میتوان با استفاده از صفتها، برنامهای پویاتر ایجاد نمود، مهمترین عامل در فهم و درک کامل مبحث خواهد بود. درباره Reflection نیز در آینده در یان سایت مفصلا توضیح خواهم داد.
خلاصه :
در این درس با صفتها آشنا شدید. یاد گرفتید که چگونه از صفتهای موجود در .Net Framework استفاده کرده و همچنین چگونه صفتهای شخصی و دلخواه خود را تولید نمایید. همچنین با پارامترهای صفتها و انواع آنها و نیز، عناصری که صفتها بر روی آنها اعمال میشوند آشنا شدید. در انتهای درس نیز به مختصر درباره Reflection و چگونگی استفاده از صفتها در زمان اجرا صحبت کردیم. امیدوارم مفید واقع شده باشد.