Object Class چیست؟
در دات نت کلاس Object Class یک کلاس پایه (Base Class) برای تمام کلاس هاست. این کلاس Object Class در فضای نام System قرار دارد:
1 |
using System |
هر کلاسی در #C، به صورت مستقیم یا غیر مستقیم از کلاس Object Class ارث برده است. اگر کلاسی از کلاس دیگر ارث نبرده باشد، پس مستقیما از کلاس Object Class ارث برده است. در غیر این صورت به صورت غیر مستقیم از آن ارث برده است. بنابر این، تمام متد های Object Class در تمام کلاس ها، قابل دسترسی اند. پس می توان گفت که از Object Class به عنوان پایه ی وراثت (یکی از ارکان شئ گرایی) در سی شارپ، یاد می شود.
هدف اصلی Object Class فراهم کردن سرویس های low-level برای کلاس های ارث برده شده است.در سی شارپ، BCL یا NET Base Class Library یک نام مستعار دارد که یک Object Class به نام Object است.
انواع Type ها
دو نوع type در #C وجود دارد:
- Reference Type
- Value Type
هنگام استفاده از کلاس ValueType ، آیتم های Value Type به صورت غیر مستقیم از Object Class ارث می برند. کلاس ValueType ، متد های Virtual متعلق به Object Class را Override می کند و پیاده سازی های مناسبی را برای Value Type ها، فراهم می کند.
در زبان های برنامه نویسی دیگر، type های ساخت یافته مانند: int, double, float و … ویژگی های شئ گرایی را ندارند. بنابر این برای شبیه سازی ویژگی های شئ گرایی، آنها باید در داخل object ها، بسته بندی شوند. اما در #C نیازی به این کار نیست، زیرا Value Type ها از System.ValueType ارث برده اند و فراتر از آن از System.Object ارث برده اند. پس در سی شارپ، Value Type ها شبیه Reference Type ها هستند. Reference Type ها به صورت مستقیم یا غیر مستقیم از Object Class ارث برده اند. (از طریق استفاده از دیگر Refrence Type ها)
به شکل زیر دقت کنید (Struct یک Value Type است):

مثال:
اجزاء Object Class
Constructor: متد سازنده Object ، یک Instance از کلاس Object Class را مقدار دهی می کند. این Constructor توسط Constructor های موجود در کلاس های دیگر، فراخوانده می شود.
Methods: هشت متد زیر، در کلاس Object Class وجود دارند که امکان Override آنها نیز وجود دارد:
نام متد | توضیحات |
---|---|
Equals(Object) | این متد مشخص می کند که آیا Object مشخص شده با Object فعلی، برابر است یا خیر. |
Equals(Object, Object) | این متد مشخص می کند که آیا این دو نمونه Object با هم برابر هستند یا خیر. |
()Finalize | به Object اجازه ی رهاسازی Resource ها را می دهد، همچنین دیگر عملیات های CleanUp را اجرا می کند قبل از آنکه توسط Garbage Collection تصاحب شوند. |
()GetHashCode | به عنوان Hash Function پیشفرض عمل می کند. |
()GetType | Type نمونه شئ فعلی را بر می گرداند. |
()MemberwiseClone | از شئ فعلی، یک Shallow Copy می سازد. |
ReferenceEquals(Object, Object) | این متد مشخص می کند که آیا این دو نمونه Object ، واقعا یک نمونه Object هستند یا خیر. |
()ToString | این متد، String ای که نشان دهنده ی Object فعلی است را بر می گرداند. |
()GetHashCode
- این متد، برای برگرداندن Hash Code متعلق به Instance فعلی به کار می رود.
- یک HashCode یک مقدار عددی است که برای درج (Insert) و شناسایی در کالکشن Hash-Based به کار می رود.
- GetHashCode یک متد است که الگوریتم ها با استفاده از آن می توانند خیلی سریع، برابری Object ها را بررسی کنند.
1 |
public virtual int GetHashCode |
- این متد، یک Integer از نوع 32 بیتی را بر می گرداند.
دو Object ای که HashCode متفاوت دارند یعنی برابر نیستند اما عکس این موضوع، صادق نیست. یعنی وجود دو HashCode یکسان به معنای برابری دو Object نیست. چون Object های مختلف هم امکان دارد که HashCode های یکسان داشته باشند.
Equals(object)
مشخص می کند که آیا Object تعیین شده با Object فعلی برابر است یا خیر.
1 |
public virtual bool Equals (object? obj); |
چرا در مثال بالا، خروجی عبارت False را نشان می دهد؟
چون متد Equals(object) متعلق به Object Class فراخوانی شده است. در این پیاده سازی، بررسی می شود که آیا دو شئ کاملا یکسان هستند یا خیر. خب طبیعتا در مثال بالا، درست است که در این دو شئ، مقدار هر دوName برابر Ali است اما هر نمونه شئ به یک آدرس متفاوت در Memory اشاره می کند.
اگر به جای کد زیر
1 2 3 |
var s1 = new Student("Ali"); var s2 = new Student("Ali"); |
کد زیر را می نوشتیم، نتیجه برابر True می شد. چون هر دو نمونه شئ به یک آدرس memory اشاره می کنند.
1 2 3 |
var s1 = new Student("Ali"); var s2 = s1; |
اگر بخواهیم دو شئ ای که در آدرس های memory مختلفی هستند اما اعضاء آنها با هم برابر هستند را مقایسه کنیم، مجبور هستیم که متد Equals(object) را Override کنیم.
به مثال زیر دقت کنید:
تفاوت Equals(object) با == در مقایسه String
زمانی که از == برای مقایسه استفاده می کنیم، در واقع داریم Reference آنها را مقایسه می کنیم، چون این عملگر متعلق به Object.ReferenceEquals است. اما Equals یک Virtual Method است و نسخه ی Override شده ی آن در مورد کلاس String تنها محتویات String را مقایسه می کند.
نگاهی به Shallow Copy و Deep Copy
هنگامی که یک object در Object دیگر کپی می شود، هر دو Object یک Memory Address یکسان خواهند داشت.در واقع هنگامی که از عملگر = استفاده می کنیم، آدرس آن را کپی می کنیم و Object آن کپی نمی شود. مگر آنکه Value Type ای در کار باشد.
Shallow Copy (کپی سطحی)
به عمل ایجاد یک شئ جدید و Copy کردن فیلد های Value Type متعلق به شئ فعلی در داخل شئ جدید Shallow Copy می گویند. اما زمانی که دیتا از نوع Reference Type باشد تنها Reference کپی می شود و نه خود شئ ارجاع شده. بنابر این Original و Clone ، هر دو به یک شئ یکسان ارجاع دارند.
و استفاده از آن:
Deep Copy (کپی عمیق)
به عمل ایجاد شئ جدید از روی شئ فعلی و کپی کردن تمام فیلد های آن، اعم از Value Type و Reference Type ، کپی عمیق یا Deep Copy می گویند. در مثالی که قبلا ارائه شد، یک متدی به نام Deep Copy وجود دارد، مهم نیست که فیلد ها Value Type یا Reference Type باشند. Deep Copy یک کپی کامل از اطلاعات می سازد و آن را در مکان های مختلفی از Memory ذخیره می کند.
Boxing و Unboxing
Boxing و Unboxing یک نگاه جامع به Type ها را فراهم می کنند. (فارغ از اینکه یک type از چه نوعی باشد (Value یا (Reference، با آن یک جور رفتار می شود.
نکته: Value Type در حافظه Stack ذخیره می شود، در حالی که Reference Type در حافظه Heap ذخیره می شود.
Boxing
تبدیل یک Value Type (int, Char, …) به Reference Type (object)را Boxing می گویند.
;int num = 23
object Obj = num; // boxing
به عنوان مثال:
Unboxing
تبدیل یک Reference Type به یک Value Type را Unboxing می گویند.
;int num = 23
object Obj = num; // boxing
int i = (int)Obj; // unboxing
به عنوان مثال: