میدان دید(scope) متغیرها در سی شارپ

Ratings
(0)

 

به جایی که یک متغیر در دسترس است، میدان دید(scope) آن متغیر گفته می شود. میدان دید متغیرها یک موضوع مهم است و در زیر در قالب یک مثال معرفی شده است. در مثال خودتان امتحان کنید زیر، یک متغیر در یک میدان دید تعریف شده است و در یک میدان دید متفاوت تلاش می کنیم از آن استفاده کنیم:


خودتان امتحان کنید: میدان دید متغیرها : Ch06Ex01\Program.cs

1. در مثال خودتان امتحان کنید شماره 1 در فصل 6، یعنی در این مقاله، تغییرات زیر را اعمال کنید:

class Program
{
  static void Write()
  {
    WriteLine($"myString = {myString}");
  }
  static void Main(string[] args)
  {
     string myString = "String defined in Main()";
     Write();
     ReadKey();
  }
}

 2. کدها را کامپایل کنید و به خطای و هشداری که در لیست خطاها، نشان داده می شود، توجه کنید:

The name 'myString' does not exist in the current context
The variable 'myString' is assigned but its value is never used

این کدها چگونه کار می کند

چه اشتباهی رخ داد؟ متغیر myString که در بدنه ی main یعنی در تابع Main()، از برنامه تعریف شده است، در تابع Write() در دسترس نیست. علت این عدم دسترسی، این است که متغیرها دارای محدوده یا میدان دیدی(scope) هستند که در آن معتبر هستند. این میدان دید شامل بلوک کدی است که آنها در آن تعریف شده اند. 

این بلوک های کد در تابع ها، با بلوک های کدی که آنها فراخوانی می شوند، متفاوت است. درون تابع Write() نام myString تعریف نشده است و در این تابع استفاده از متغیر myString که در Main() تعریف شده است، امکان پذیر نیست، زیرا  از میدان دید خارج است. و تنها می تواند در داخل متد Main() مورد استفاده قرار گیرد. 

در حقیقت ما می توانیم یک متغیر کاملاً متفاوت به نام myString را در تابع Write() داشته باشیم. سعی کنید کدها را به صورت زیر اصلاح کنید:

class Program
{
  static void Write()
  {
     string myString = "String defined in Write()";
     WriteLine("Now in Write()");
     WriteLine($"myString = {myString}");
  }
  static void Main(string[] args)
  {
    string myString = "String defined in Main()";
    Write();
    WriteLine("\nNow in Main()");
    WriteLine($"myString = {myString}");
    ReadKey();
  }
}

این کد کامپایل می شود و نتیجه ی آن در تصویر 6.5 نشان داده شده است. 

(تصویر 6.5)

نتیجه ی اجرای کدها در سی شارپ

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

1. تابع Main() یک متغیر رشته ای به نام myString را تعریف و مقداردهی اولیه می کند. 

2. تابع Main() کنترل را به تابع Write() واگذار می کند. 

3. در تابع write() یک متغیر رشته ای به نام myString تعریف و مقداردهی اولیه شده است؛ که با متغیر myString که در تابع Main() تعریف شده است، متفاوت می باشد. 

4. تابع Write() یک رشته را در کنسول برمی گرداند که حاوی مقدار متغیر myString است، که در تابع Write() تعریف شده است. 

 5. تابع Write() کنترل را به تابع Main() برمی گرداند. 

6. تابع Main()، یک رشته را در کنسول برمی گرداند که حاوی مقدار متغیر myString است، که در تابع Write() تعریف شده است.

به متغیرهایی که میدان دید آنها در یک تابع قرار دارد، یعنی فقط در این تابع در دسترس هستند، متغیرهای محلی گفته می شود. این امکان نیز وجود دارد تا متغیرهایی سراسری(global) را تعریف کنیم، به طوری که میدان دید آنها، چندین تابع را پوشش می دهد. کدهای خود را به صورت زیر اصلاح کنید:

class Program
{
  static string myString;
  static void Write()
  {
    string myString = "String defined in Write()";
    WriteLine("Now in Write()");
    WriteLine($"Local myString = {myString}");
    WriteLine($"Global myString = {Program.myString}");
   }
  static void Main(string[] args)
  {
    string myString = "String defined in Main()";
    Program.myString = "Global string";
    Write();
    WriteLine("\nNow in Main()");
    WriteLine($"Local myString = {myString}");
    WriteLine($"Global myString = {Program.myString}");
    ReadKey();
  }
}

اکنون نتیجه به صورت زیر خواهد بود: 
(تصویر 6.6)آموزش سی شارپ تصویر نتیجه

 در اینجا یک متغیر دیگر به نام myString اضافه کرده ایم؛ این متغیر به صورت زیر تعریف شده است:

static string myString;

 دوباره، به کلمه ی کلیدی static نیاز پیدا کرده ایم. بدون اینکه وارد جزئیات شویم، این را بدانید که در این نوع برنامه های کنسول، برای تعریف متغیرهای سراسری، یا باید از کلمه ی کلیدی static استفاده کنیم یا از کلمه ی کلیدی const. اگر می خواهید مقدار این متغیر سراسری را اصلاح کنید، نیاز دارید از کلمه ی کلیدی static استفاده کنید، زیرا کلمه ی کلیدی const از تغییر مقدار متغیر جلوگیری می کند. 

 برای تمایز قائل شدن بین این متغیر و متغیرهای محلی، در تابع Main() و Write()، که (این دو متغیر) نام های یکسانی هم دارند، باید نام آنها را به صورت کاملاً توصیفی مرتب کنیم. همان طور که در فصل 3 توضیح داده شد. در اینجا به با استفاده از دستور Program.myString به نسخه ی سراسری(global) این متغیر اشاره می کنیم. این تنها وقتی ضروری است که متغیرهای سراسری(global) و محلی(local) داشته باشیم که نام یکسانی دارند. 

 اگر برای متغیر myString نسخه ی محلی(local) وجود نداشته باشد، به سادگی می توانیم از myString به جای Program.myString برای اشاره به این متغیر سراسری استفاده کنیم. وقتی که یک متغیر محلی داریم که یک متغیر سراسری نیز با همین نام وجود دارد، گفته می شود که این متغیر سراسری پنهان است. ما می توانیم مقدار این متغیر سراسری را با استفاده از دستور زیر در تابع Main() تنظیم کنیم:

Program.myString = "Global string";

و با استفاده از دستور زیر در تابع  Write() می توانیم به مقدار آن دسترسی داشته باشیم:

WriteLine($"Global myString = {Program.myString}");

ممکن است تعجب کنید که چرا نباید تنها از این روش برای تبادل داده با تابع ها، به جای پاس دادن پارامترها که اخیراً گفته شد، استفاده کنیم. در واقع موقعیت هایی وجود دارد که این یک راه قبول برای تبادل داده ها است. بعنوان مثال، اگر در حال نوشتن یک آبجکت تکی هستید که به صورت یک پلاگین یا یک اسکریپت کوتاه، برای پروژه های بزرگتر استفاده می شود؛ اما سناریوهای زیادی وجود دارد که این ایده ی خوبی نیست. 

متداول ترین مسئله در استفاده از متغیرهای سراسری، مربوط به مدیریت همزمانی(management of concurrency) است. بعنوان مثال، یک متغیر سراسری می تواند در متدهای متعدد در داخل یک کلاس یا در تردهای(thread) مختلف، نوشته یا خوانده شود. آیا می‌توان مطمئن بود که مقدار درون متغیر سراسری، اگر بتوانیم تردها و متدهای مختلفی را در آن بنویسیم، حاوی داده ی معتبری است؟ بدون برخی کدهای همگام سازی اضافی(extra synchronization code)، پاسخ احتمالاً منفی است. علاوه بر این، در طول زمان، ممکن است قصد واقعی در استفاده از متغیر سراسری فراموش شود و بعداً به دلیل دیگری مورد استفاده قرار گیرد. بنابراین، انتخاب اینکه آیا از متغیرهای سراسری استفاده شود یا خیر، بستگی به کاربرد مورد نظر از تابع مورد نظر دارد. 

مشکل استفاده از متغیرهای سراسری، این است که آنها عموماً برای کارکردهای «همه منظوره ای که  نامناسب هستند. که می‌تواند با هر داده‌ای که ارائه می‌دهیم کار کند، نه فقط با داده‌های یک متغیر سراسری خاص. کمی بعد در مورد این موضوع به طور عمیق تری بحث خواهیم کرد. 

 

  • بازدید: 78

نوشتن دیدگاه

لطفا نظرات خود را بیان کنید. به سوالات در سریع ترین زمان پاسخ داده خواهد شد.اما به نکات زیر توجه کنید:
1. سعی کنید نظرات شما مرتبط با مقاله ی مورد نظر باشد، در غیر این صورت پاسخ داده نخواهد شد.
2. سوالات خود را به صورت کوتاه بیان کنید و از پرسیدن چند سوال به طور همزمان خودداری کنید.
3. سوال خود را به طور واضح بیان کنید و از کلمات مبهم استفاده نکنید.

ارسال