تفاوت بین یک کلاس استاتیک، متدی استاتیک و یا متغیر عضو استاتیک چیست؟ چه زمانی باید از آنها استفاده کرد و لزوم بودن آنها چیست؟
برای پاسخ دادن به این سؤالات باید از نحوهی تقسیم بندی حافظه شروع کرد.
RAM برای هر نوع پروسهای که در آن بارگذاری میشود به سه قسمت تقسیم میگردد: Stack ، Heap و Static (استاتیک در دات نت در حقیقت قسمتی از Heap است که به آن High Frequency Heap نیز گفته میشود).
این قسمت استاتیک حافظه، محل نگهداری متدها و متغیرهای استاتیک است. آن متدها و یا متغیرهایی که نیاز به وهلهای از کلاس برای ایجاد ندارند، به صورت استاتیک ایجاد میگردند. در سی شارپ از واژه کلیدی static برای معرفی آنها کمک گرفته میشود. برای مثال:
class MyClass
{
public static int a;
public static void DoSomething();
}
در این مثال برای فراخوانی متد DoSomething نیازی به ایجاد یک وهله جدید از کلاس MyClass نمیباشد و تنها کافی است بنویسیم:
MyClass.DoSomething(); // and not -> new MyClass().DoSomething();
نکتهی مهمی که در اینجا وجود دارد این است که متدهای استاتیک تنها قادر به استفاده از متغیرهای استاتیک تعریف شده در سطح کلاس هستند. علت چیست؟
به مثال زیر دقت نمائید:
class MyClass
{
// non-static instance member variable
private int a;
//static member variable
private static int b;
//static method
public static void DoSomething()
{
//this will result in compilation error as “a” has no memory
a = a + 1;
//this works fine since “b” is static
b = b + 1;
}
}
در این مثال اگر متد DoSomething را فراخوانی کنیم، تنها متغیر b تعریف شده، در حافظه حضور داشته (به دلیل استاتیک معرفی شدن) و چون با روش فراخوانی MyClass.DoSomething هنوز وهلهای از کلاس مذکور ایجاد نشده، به متغیر a نیز حافظهای اختصاص داده نشده است و نامعین میباشد.
بر این اساس کامپایلر نیز از کامپایل شدن این کد جلوگیری کرده و خطای لازم را گوشزد خواهد کرد.
اکنون تعریف یک کلاس به صورت استاتیک چه اثری را خواهد داشت؟
با تعریف یک کلاس به صورت استاتیک مشخص خواهیم کرد که این کلاس تنها حاوی متدها و متغیرهای استاتیک میباشد. امکان ایجاد یک وهله از آنها وجود نداشته و نیازی نیز به این امر ندارند. این کلاسها امکان داشتن instance variables را نداشته و به صورت پیش فرض از نوع sealed به حساب خواهند آمد و امکان ارث بری از آنها نیز وجود ندارد. علت این امر هم این است که یک کلاس static هیچ نوع رفتاری را تعریف نمیکند.
پس با این تفاسیر چرا نیاز به یک کلاس static ممکن است وجود داشته باشد؟
همانطور که عنوان شد یک کلاس استاتیک هیچ نوع رفتاری را تعریف نمیکند بنابراین بهترین مکان است برای تعریف متدهای کمکی که به سایر اعضای کلاسهای ما وابستگی نداشته، عمومی بوده، مستقل و متکی به خود هستند. عموما متدهای کمکی در یک برنامه به صورت مکرر فراخوانی شده و نیاز است تا به سرعت در دسترس قرار داشته باشند و حداقل یک مرحله ایجاد وهله کلاس در اینجا برای راندمان بیشتر حذف گردد.
برای مثال متدی را در نظر بگیرید که بجز اعداد، سایر حروف یک رشته را حذف میکند. این متد عمومی است، وابستگی به سایر اعضای یک کلاس یا کلاسهای دیگر ندارد. بنابراین در گروه متدهای کمکی قرار میگیرد. اگر از افزونهی ReSharper استفاده نمائید، این نوع متدها را به صورت خودکار تشخیص داده و راهنمایی لازم را جهت تبدیل آنها به متدهای استاتیک ارائه خواهد داد.
با کلاسهای استاتیک نیز همانند سایر کلاسهای یک برنامه توسط
JIT compiler رفتار میشود، اما با یک تفاوت. کلاسهای استاتیک فقط یکبار هنگام اولین دسترسی به آنها ساخته شده و در قسمت High Frequency Heap حافظه قرار میگیرند. این قسمت از حافظه تا پایان کار برنامه از دست garbage collector در امان است (بر خلاف garbage-collected heap یا object heap که جهت instance classes مورد استفاده قرار میگیرد)
نکته:
در برنامههای ASP.Net از بکارگیری متغیرهای عمومی استاتیک برحذر باشید (از static fields و نه static methods). این متغیرها بین تمامی کاربران همزمان یک برنامه به اشتراک گذاشته شده و همچنین باید مباحث قفلگذاری و امثال آنرا در محیطهای چند ریسمانی هنگام کار با آنها رعایت کرد (
thread safe نیستند).