#C چیست

سی شارپ (به انگلیسی: #C )یک زبان برنامه نویسی همگردان، سطح بالا، شیءگرا، ساخت یافته، رویداد محور، تابعی، دستوری و جنریک است که توسط شرکت مایکروسافت در سال 2000 میلادی از خانوادهٔ زبان‌های چارچوب دات‌نت معرفی شد. زبان #C همچنین از خانواده زبان‌های برنامه‌نویسی سی نیز است.

زبان #C، یک زبان برنامه‌نویسی چند الگویی و منظم شده مدل‌های تابعی، اَمری، عمومی، شیءگرا و جز گرا و در بستر چارچوب دات نتمی‌باشد. این زبان توسط شرکت مایکروسافت و جزئی از دات نت به وجود آمد و بعداً استانداردهای ECMA و ISO را نیز دربر گرفت. #C یکی از ۴۴ زبان برنامه‌نویسی است که توسط زمان اجرای زبان مشترک از چارچوب دات‌نت پشتیبانی می‌شوند و در همه جا به وسیلهمایکروسافت ویژوال استودیو شناخته می‌شود.

زبان #C با قدرت و در عین حال سطح بالایی خود توانسته توجه بسیاری از برنامه نویسان را به خود جلب کند.

این زبان برپایه سادگی، مدرن بودن، همه منظوره و شئ گرا بودن ساخته شد. آندرس هجلزبرگ، طراح زبان برنامه‌نویسی دلفی، سرپرستی تیم طراحان زبان #C را بر عهده داشت. این زبان دارای دستوری شیءگرا مشابه ++C است و به شدت از زبان‌های جاوا و دلفینیازمندمدرکتأثیر پذیرفته‌است. در ابتدا نام این زبان COOL بود که مخفف C like Object Oriented Language بود، هر چند در ژوئیه ۲۰۰۰م، زمانی کهمایکروسافت پروژه را عمومی اعلام کرد، اسم آن به #C تغییر پیدا کرد.

اهداف طراحی زبان

  • استاندارد ECMA این اهداف طراحی زبان را برای #C برآورده می‌سازد:
  • #C یک زبان برنامه‌سازی ساده، مدرن، برای اهداف عمومی و شیءگرا است.
  • به دلیل اهمیت داشتن موضوع نیرومندی و دوام و بهره‌وری برنامه‌نویس، زبان دارای چک‌کننده Strong Type، چک‌کننده مرزهای آرایه، تشخیص حالت‌هایی که یک متغیر مقداردهی اولیه نشده‌است، قابلیت انتقال کدها و Garbage Collection خودکار است.
  • این زبان برای استفاده در اجزای توسعه نرم‌افزار برای دستیابی به مزایای سامانه‌های توزیعی در نظر گرفته شده‌است.
  • قابلیت انتقال برنامه‌نویس بسیار مهم است، خصوصاً برای آن دسته از برنامه‌نویسانی که با زبان‌های C و C++ آشنا هستند.
  • پشتیبانی از این زبان برای بین‌المللی شدن بسیار مهم است.
  • زبان #C برای نوشتن برنامه‌ها برای سامانه‌های تعبیه شده و میزبان در نظر گرفته شده‌است، سیستم‌عامل‌های پیچیده بسیار بزرگ گرفته تا توابع اختصاصی بسیار کوچک.
  • هر چند برنامه‌های نوشته شده با #C طوری هستند که از لحاظ حافظه و پردازنده مورد نیاز مقرون به صرفه باشند، ولی خود زبان از لحاظ اندازه و کارایی به خوبی زبان‌های C و اسمبلی نیست.

تاریخچه #C

در سال ۱۹۹۹م، شرکت سان مایکروسیستمز اجازه استفاده از زبان برنامه‌نویسی جاوا را در اختیار شرکت مایکروسافت قرار داد تا در سیستم‌عامل خود از آن استفاده کند. جاوا در اصل به هیچ پلت فرم یا سیستم‌عاملی وابسته نبود، ولی مایکروسافت برخی از مفاد قرار داد را زیر پا گذاشت و قابلیت مستقل از سیستم‌عامل بودن جاوا را از آن برداشت. شرکت سان پرونده‌ای علیه مایکروسافتدرست کرد و مایکروسافت مجبور شد تا زبان شیءگرای جدیدی با کامپایل جدید که به ++C شبیه بود را درست کند. در طول ساخت دات نت، کلاس‌های کتابخانه‌ای با زبان و کامپایلر SMC نوشته شدند. در سال ۱۹۹۹ آندرس هلزبرگ گروهی را برای طراحی زبانی جدید تشکیل داد که در آن زمان نامش Cool بود و همانند C بود با خواص شیءگرایی. مایکروسافت در نظر داشت اسم این زبان را تا آخر COOL قرار دهد، ولی به دلیل مناسب نبودن برای اهداف تجاری این کار را نکرد. در ارائه و معرفی رسمی چارچوب دات‌نت در PDC در سال ۲۰۰۰ این زبان به #C تغییر نام یافت و کتابخانه کلاس‌ها و runtime در ای‌اس‌پی‌دات‌نت به #C منتقل شدند. مدیر و سرپرست طراحان در مایکروسافت آندرس هلزبرگ بود که تجربه قبلی او در طراحی Framework و زبان‌های برنامه سازی++Borland، دلفی، Turbo Pascal، ویژوال سی++ به آسانی در دستورالعمل‌های #C قابل رویت است و به همان خوبی در هسته CLR.

ویژگی‌های #C

برخی از تفاوت‌های زبان #C با زبان‌های C و ++C عبارتند از:

  • هیچ تابع یا متغیر سراسری(Global) وجود ندارد، تمام متدها و اعضا بایستی در داخل کلاس‌ها تعریف شوند. این امر ممکن است، هر چند برای استفاده از متغیرها و توابع عمومی باید از متدها و متغیرها در کلاس‌های عمومی استفاده کرد.
  • متغیرهای عمومی، بر خلاف زبان‌های C و ++C، نمی‌توانند بلاک‌های پیوستی را در بر بگیرند.
  • #C دارای یک نوع داده بولی است (bool). برخی از عبارت‌ها مانند while و if که شرطی هستند، نیازمند یک عبارت نوع بولی هستند. همان‌طور که ++C نیز دارای نوع داده بولی است، این نوع داده به راحتی می‌تواند به یا از Integerها تبدیل شود، و عبارتی مانند (if(a نیازمند این امر است که a از یک نوع قابل تبدیل به bool یا اشاره گر باشد. کامپایلر #C برنامه‌نویس را در این شرایط مجبور به استفاده از عباراتی می‌کند که به درستی یک مقدار bool را برمی‌گردانند؛ بنابراین دستوری مانند (if(a = b باعث بروز خطا می‌شوند. (به جای = بایستی از == استفاده شود)
  • در سی شارپ، اشاره گرهای به حافظه بایستی فقط در داخل بلوکهای unsafe استفاده شوند و برنامه در این حالت برای اجرا نیاز به اجازه از کاربر دارد. بیشتر دسترسی شی از طریق شی امن است که یا همیشه در حال اشاره به شی صحیح موجود است یا یک مقدار Null دارد. اشاره گری به شی به درد نخور یا بلاک حافظه رندم غیرممکن است. اشاره گر نا امن می‌تواند به نمونه‌ای از value-type، آرایه، رشته یا بلاکی که حافظه به آن داده شده‌است اشاره نماید. کدی که به عنوان نا امن علامت نخورده باشد، هنوز می‌تواند اشاره گرها را از سامانه بازیابی یا در آن ذخیره کند ولی نمی‌تواند مرجع جدیدی به آن‌ها اختصاص دهد.
  • حافظه ساماندهی شده نمی‌تواند صریحاً آزاد شود، ولی به‌طور خودکار به عنوان به درد نخور تلقی می‌شود. انتخاب آدرس‌های به درد نخور حافظه نفوذ ناپذیر است. هم چنین #C با استفاده از عبارات، پشتیبانی مستقیمی از پایان اجباری می‌کند (پشتیبانی از اصطلاح Resource Acquisition Is Initialization).
  • وراثت چندگانه از کلاس‌ها در این زبان پشتیبانی نمی‌شود. البته یک کلاس امکان ارث بری از تعداد نامحدود واسط‌ها را دارد. پشتیبانی نکردن از وراثت چندگانه به دلیل اهداف معماری این زبان در CLI و برای جلوگیری از پیچیدگی است. در عوض می‌توان از اینترفیس‌های مختلف استفاده کرد. یعنی برای یک کلاس که احتمالاً فرزند کلاسی دیگر است (ارث برده) می‌توان چندین اینترفیس را پیاده‌سازی (Implement) نمود.
  • #C بسیار typesafe تر از ++C است. تنها تبدیلات ضمنی مثل تبدیل نوع داده کوچکتر به بزرگتر یا تبدیل نوع مشتق شده به نوع پایه به‌طور پیش‌فرض و بدون خطا صورت می‌پذیرد. هیچ تبدیل ضمنی ای میانBooleanها و Integerها وجود ندارد و هر تبدیل user-defined بایستی به صراحت با یکی از کلمات explicit یا implicit نشانه گذاری شود. تبدیل b به a در حالتی که a یک Integer و b یک double باشد در زبان C++ مجاز است اما در #C به یک خطای زمان کامپایل منجر می‌شود (بایستی به صورت explicit تعریف شود)
  • اعضای Enumeration در داخل محدوده شخصی خود قرار دارند.
  • #C قابلیت syntactic sugar را برای توابع متداول، اکسسورها و ماجول‌های کسول شده در یک کلاس به صورت ویژگی‌ها قرار داده‌است.

اکسسورها که خاصیت نیز گفته می‌شوند در زبان #C قادر به کنترل دسترسی اعضا و معتبرسازی داده‌ها هستند.

  • تمام انواع بازتابی(Reflection) و بازیابی(Recovery) قابل استفاده‌است.
  • در حال حاضر (۳ ژوئن ۲۰۰۸) دارای ۷۷ کلمۀ رزرو شده‌ ( کلمۀ کلیدی ) است.

ساختمان داده (ساختار و ذخیره‌سازی داده) در #C

این کامپایلر در مقابل زبان‌های C یا ++C دارای ساختار بسیار متفاوتی است که دانستن آن به برنامه‌نویس امکان نوشتن برنامه‌های بسیار بهینه را خواهد داد.

رشته‌ها

در C یا ++C ساختار رشته به صورت ارایه‌ای از نوع char بود که امکان اضافه کردن به رشته را محدود می‌کرد به دلیل ثابت بودن طول در آغاز تعریف ولی در #C دو نوع متفاوت رشته وجود دارد؛ که یکی به صورت آرایه‌ای با طول ثابت ۲۵۶(در عمل ۲۵۵)موجوداست (به صورت پیش فرض) و در صورتی که با کمبود جا روبرو شود فضای جدید (بزرگتر) یافته و به ان انتقال می‌دهد؛ ولی در نوع دوم رشته‌ها از لیست پیوندی استفاده می‌شود.

سامانه یکپارچه شده

#C دارای یک سامانه نوع یکپارچه‌است که به آن CTS می‌گویند. این بدان معناست که تمام انواع، شامل موارد اصلی مانند Integerها، مشتق شده از System.Object هستند. به عنوان مثال، هر نوع یک متد به نام ToString() را به ارث می‌برد. بخاطر کارایی، انواع اولیه (و انواع مقداری) به‌طور داخلی فضایی برای آن‌ها بر روی پشته در نظر گرفته می‌شود.

انواع داده

CTS داده‌ها را به دو نوع تقسیم می‌کند:

  • نوع مقداری (Value Type)
  • نوع مرجعی (Refrence Type)

انواع داده‌ای توده ساده‌ای از داده می‌باشند. نمونه‌های انواع داده‌ای نه هویت مرجعی دارند و نه مفاهیم مقایسه مراجع را. برای مقایسه برابری یا عدم برابری انواع داده‌ای، خود مقدار داده‌ها را با یکدیگر مقایسه می‌کنیم مگر اینکه عملگرهای مشابه دوباره تعریف شده باشند. مقادیر داده‌های مرجعی همیشه یک مقدار پیش‌فرض دارند و همیشه می‌توانند ایجاد یا کپی شوند. یکی دیگر از محدودیت‌های انواع داده‌ای این ات که آن‌ها نمی‌توانند از یکدیگر مشتق شوند (ولی می‌توانند اشتراکاتی داشته باشند) و هم چنین نمی‌توانند در سازنده مقدار دهی اولیه شوند. مثالی از انواع داده‌ای، بعضی از انواع اولیه مانند int و float و char و System.DateTime می‌باشند. در مقابل، انواع مرجعی مفهوم تعریف مرجعی را دارند (که در آن هر نمونه از نوع مرجع، به‌طور ذاتی از دیگر نمونه‌ها جدا می‌شود، حتی اگر داده هر دو نمونه یکی باشد). این دقیقاً نمونه مشابه مقایسه تساوی یا عدم تساوی داده‌های مرجعی است، که در آن آزمایش برای مرجع‌ها از داده‌ای‌ها سریع تر است. در کل نه همیشه امکان تعریف نمونه مرجعی وجود دارد و نه امکان کپی یا نمایش مقادیر مقایسه دو نمونه؛ ولی به هر حال انواع مرجعی خاص می‌توانند این اعمال را از طریق سازنده‌های عمومی یا اجرای واسط‌های مشابه (مثل ICloneable یا IComparable) انجام دهند. نمونه‌هایی از انواع مرجعی، اشیاء، System.String و Sysmet.Array می‌باشند. هر دو نوع داده قابلیت انعطاف توسط تعریف به وسیله کاربر را دارند. در واقع وقتی ما نوع داده‌ای را به تابع ای ارسال می‌کنیم، آدرس داده نیز فرستاده می‌شود. البته این امر پیش‌فرض است ولی برای داده‌های مثل آرایه، رشته‌ای، آدرس فرستاده می‌شود و ارسال از نوع مرجع می‌شود

Boxing و UnBoxing

Boxing عمل تبدیل مقدار نوع داده‌ای به نوع مرجع مشابه آن می‌باشد.

مثال:

int foo = 42;// Value type...
object bar = foo;//foo is boxed to bar.

UnBoxing عمل تبدیل نوع مرجع به نوع داده‌ای می‌باشد. مثال:

int foo = 42;// Value type.
object bar = foo;// foo is boxed to bar.
int foo2 = (int)bar;// Unboxed back to value type.

#C به برنامه‌نویس با استفاده از کلمه کلیدی Struct اجازه می‌دهد تا انواع مقداری User-defined را ایجاد کند. از دیدگاه برنامه‌نویسی، آن‌ها کلاس‌های سبک وزن به نظر می‌رسند. برخلاف کلاس‌ها (که بر روی heap قرار می‌گیرند) و شبیه به انواع اولیه استاندارد مانند انواع مقداری Structها نیز بر روی پشته قرار می‌گیرند. آن‌ها همچنین می‌توانند قسمتی از یک شئ باشند، یا در یک آرایه مرتب شوند، بدون حافظه غیر مستقیمی که به‌طور معمول برای انواع کلاس تخصیص می‌یابد.

ویژگی‌های جدید در سی شارپ ۲٫۰

ویژگی‌های جدید در #C چارچوب دات‌نت SDK ۲٫۰ (مطابق با سومین ویرایش استاندارد ECMA-۳۳۴):

کلاسهای partial

کلاس‌های Partial اجازه اجرای کلاس‌ها از بیش از یک سورس فایل را می‌دهند. این امر اجازه می‌دهد تا کلاس‌های بسیار بزرگ را قطعه قطعه کنیم و همچنین برای زمانی که برخی قسمت‌های یک کلاس به‌طور خودکار تولید می‌شوند مفید است.

file.cs:

public partial class MyClass
{
    public MyClass()
    {
// implementation
    }
}

file2.cs:

public partial class MyClass
{
    public void SomeMethod()
    {
// implementation
    }
}

Genericها

genericها یا نوع‌های پارامتری شده یا چندریختی‌های پارامتری یک ویژگی جدید چارچوب دات‌نت ۲٫۰ است که به وسیله #C پشتیبانی می‌شود. برخلاف Templateهای سی پلاس پلاس، در این انواع به جای اینکه نمونه‌سازی توسط کامپایلر انجام شود، در زمان اجرا صورت می‌گیرد، بنابراین می‌توانند چند زبانه باشند در حالی که ++C نمی‌تواند. آن‌ها دارای ویژگی‌هایی هستند که به‌طور مستقیم توسط Templateهای ++C پشتیبانی نمی‌شوند مانند نوع محدودیت‌ها در پارامترهای Generic با استفاده از رابط‌ها(Interface). سی شارپ از پارامترهای‌های Generic بدون نوع پشتیبانی نمی‌کند. بر خلاف genericهای جاوا، generic‌های دات نت برای پارامتری کردن انواع داده‌ای در اشیاء ماشین مجازی CLI، از مفاهیم شیءگرایی استفاده می‌کنند که اجازه بهینه‌سازی و حفاظت انواع اطلاعات را می‌دهد.

کلاس‌های static

کلاس‌ها به صورت Static قابل تعریف نیستند مگر اینکه تمام اعضای آن‌ها Static باشند؛ که این امر بسیار شبیه به مفهوم مدل در زبانهای رویه‌ای است. (زبان رویه‌ای: یک زبان برنامه‌نویسی که در آن عنصر اصلی برنامه‌نویسی یک زیربرنامه‌است. مانند زبان‌های C، پاسکال و…)

یک شکل جدید از تکرارکننده با استفاده از سازنده توابع

یک شکل جدید از iterator(تکرارکننده)، با استفاده از ساختار yield return بسیار شبیه به yield زبان Python.

// Method that takes an iterable input (possibly an array) and returns all even numbers.
public static IEnumerable<int> GetEven(IEnumerable<int> numbers)
{
    foreach (int i in numbers)
    {
        if (i % 2 == 0) yield return i;
    }
}

Delegateهای ناشناس

Delegate یک شی می‌باشد که حاوی یک یا چند اشاره گر به توابع می‌باشد؛ که با Invoke کردن آن تمامی توابع اشاره شده داخل آن اجرا می‌شوند.

Delegateهای ناشناس که عملکردهای محدودی را در #C به وجود می‌آورند. کد کنار بدنه Deletage ناشناس، دسترسی کامل برای خواندن یا نوشتن در متغیرهای عمومی، پارامترهای توابع و اعضای کلاسهای دارای محدوده Deletage را دارد ولی پارامترهای out و ref را پشتیبانی نمی‌کند. برای مثال:

int SumOfArrayElements(int[] array)
{
    int sum = 0;
    Array.ForEach(       array,
        delegate(int x)
        {
            sum += x;
        }
  );
    return sum;
}

Delegate covariance and contravariance

تبدیل گروه‌های متد به نوع Deletage در برگشت دارای covariant و در انواع پارامترها دارای contravariant هستند.

اکسسورهای یک خاصیت(get و set) می‌توانند دارای سطح دسترسی متفاوتی باشند

مثال:

string status = string.Empty;
public string Status
}
    get { return status; }// anyone can get value of this property,
    protected set { status = value; }// but only derived classes can change
it
}

نکته مهم: سطح دسترسی خاصیت نمی‌تواند بالاتر از سطح دسترسی اکسسورها باشد. به عنوان مثال private بودن خاصیت و public بودن اکسسور باعث بروز خطا می‌شود.

نوع داده Nullable

نوع داده Nullable (که با یک علامت سؤال قابل تشخیص است: int? i = null;)اجازه تخصیص مقدار null را برای انواع داده‌ای می‌دهد. این امر باعث بهبودی فعل و انفعال با پایگاه داده SQL می‌شود. در این حالت نوع ستونی INTEGER NULL در SQL به‌طور مستقیم به int? در سی شارپ تبدیل می‌شود.

داده‌های Nullable در آخرین لحظات اوت ۲۰۰۵ اضافه شدند چند هفته مانده به اتمام کار اداری و برای بهبود زبان. متغیر Null در حقیقت خالی نیست، بلکه نمونه‌ای است از struct Nullable<T> با ویژگی HasValue مساوی false. وقتی در برنامه قرار می‌گیرد، خود به خود نمونه خالی در آن قرار می‌گیرد، نه مقدار خود آن، در نتیجه اشاره گر مقصد همیشه غیر Null می‌باشد، حتی برای مقادیر Null. کد زیر نضص بالا را مشخص می‌کند:

int? i = null;
object o = i;
if (o == null)
    Console.WriteLine("Correct behaviour - runtime version from September 2005 or later");
else
    Console.WriteLine("Incorrect behaviour - pre-release runtime (from before September 2005)»);

وقتی درون شی ای کپی می‌شود، نمونه Nullable به صورت تشریفاتی در آن قرار می‌گیرد و در نتیجه مقادیر و منابع Null با هم برابر می‌شوند. در گذشته این خاصیت دارای مجادله بود تا زمانی که علاوه بر چارچوب دات‌نت ۲، به هسته CLR نیز مجهز شد و همه تکنولوژی‌ها نظیر سی شارپ، ویژوال بیسیک، مایکروسافت اس‌کیوال سرور ۲۰۰۵ و مایکروسافت ویژوال استودیو ۲۰۰۵ را شامل شد.

Coalesce Operator

مقدار اولین عملوندی که null نباشد را برمی‌گرداند. (یا null، برای زمانی که تمام عملوندها null باشند)

object nullObj = null;
object obj = new Object();
return nullObj ?? obj;// returns obj

کاربرد اصلی این عملگر در قرار دادن یک مقدار nullable در یک مقدار non-nullable با استفاده از یک دستورالعمل ساده‌است.

int? i = null;
int j = i ?? 0; /* Unless i is null, initialize j to i. Else (if i is null), initialize j to 0. */

 

منبع

آشنایی با #C قسمت 1
آشنایی با #C قسمت 2
آشنایی با #C قسمت 3

0 پاسخ

دیدگاه خود را ثبت کنید

تمایل دارید در گفتگوها شرکت کنید؟
در گفتگو ها شرکت کنید.

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *