# C# 6 - The nameof Operator

یکی دیگر از قابلیت‌های جذاب نسخه‌ی جدید سی‌شارپ، عملگر nameof است. هدف اصلی آن ارائه کدهایی با قابلیت Refactoring بهتر است؛ زیرا به جای نوشتن نام فیلدها و یا متدها در صورت نیاز به صورت hard-coded، می‌

- Published: 2015-10-04
- Language: fa
- Tags: DNTips
- Canonical: https://sirwan.info/blog/fa/dntips-2232

---

> این نوشته نخستین بار در [دات‌نت تیپس](https://www.dntips.ir/post/2232) منتشر شده است.

<div class="postBody">یکی دیگر از قابلیت‌های جذاب نسخه‌ی جدید سی‌شارپ، عملگر <a href="https://github.com/dotnet/roslyn/wiki/New-Language-Features-in-C%23-6#nameof-expressions">nameof</a> است. هدف اصلی آن ارائه کدهایی با قابلیت Refactoring بهتر است؛ زیرا به جای نوشتن نام فیلدها و یا متدها در صورت نیاز به صورت hard-coded، می‌توانیم از این عملگر استفاده کنیم. به عنوان مثال در زمان صدور استثناءیی از نوع ArgumentNullException باید نام آرگومان را به سازنده‌ی این کلاس پاس دهیم. متاسفانه یکی از مشکلاتی که با رشته‌ها در حالت کلی وجود دارد این است که امکان دیباگ در زمان کامپایل را از دست خواهیم داد و با تغییر هر المنت، تغییرات به صورت خودکار به رشته پاس داده شده، به سازنده‌ی کلاس ArgumentNullException اعمال نخواهد شد:<div> <div align="left" dir="ltr" style="direction: ltr;"> <div align="left" dir="ltr" style="direction: ltr;">
<pre language="CSharp" name="code">public static void DoWork(string name)&#10;{&#10;       if (name == null)&#10;       {&#10;           throw new ArgumentNullException("name");&#10;       }&#10;}</pre>
 </div> <div style="direction: rtl; text-align: right;">اما با استفاده از عملگر nameof، کد امن‌تری را خواهیم داشت؛ زیرا همیشه نام واقعی آرگومان به سازنده‌ی کلاس <span style="text-align: start;">ArgumentNullException </span>پاس داده می‌شود:<br/> </div> <div style="direction: rtl; text-align: right;"> <div align="left" dir="ltr" style="direction:ltr;text-align:left;">
<pre language="CSharp" name="code">public static void DoWork(string name)&#10;{&#10;       if (name == null)&#10;       {&#10;           throw new ArgumentNullException(nameof(name));&#10;       }&#10;}</pre>
 </div>
اگر ReSharper را نصب کرده باشید، به شما پیشنهاد می‌دهد که از nameof به جای یک رشته‌ی جادویی (magic string) استفاده نمائید:</div> <div style="direction: rtl; text-align: right;"> <br/> </div> <div style="direction: rtl; text-align: right;"> <p style="margin-left: auto; margin-right: auto;"> <img src="/img/dntips/44093bc4872bc500c438.jpg" style="display: block; margin-left: auto; margin-right: auto; cursor: default;"/> </p> </div> <div style="direction: rtl; text-align: right;"> <br/> </div> <div style="direction: rtl; text-align: right;">یک مثال دیگر می‌تواند در زمان فراخوانی رخدادهای مربوط به <a href="https://www.dntips.ir/post/2076">OnPropertyChanged</a> باشد. در اینجا باید نام خصوصیتی را که تغییر یافته است، به آن پاس دهیم:  <br/> </div> <div style="direction: rtl; text-align: right;"> <div align="left" dir="ltr" style="direction:ltr;text-align:left;">
<pre language="CSharp" name="code">        public string Name&#10;        {&#10;            get { return _name; }&#10;            set&#10;            {&#10;                _name = value;&#10;                OnPropertyChanged("Name");&#10;            }&#10;        }</pre>
 </div>
اما با کمک عملگر nameof می‌توانیم قسمت فراخوانی متد OnPropertyChanged را به اینصورت نیز بازنویسی کنیم:</div> <div style="direction: rtl; text-align: right;"> <div align="left" dir="ltr" style="direction:ltr;text-align:left;"> <div align="left" dir="ltr" style="direction: ltr;">
<pre language="CSharp" name="code">OnPropertyChanged(nameof(Name));</pre>
 </div> </div> <div style="direction: rtl; text-align: right;">ممکن است عنوان کنید قبلاً در سی‌شارپ 5 هم می‌توانستیم از ویژگی <a href="https://www.dntips.ir/post/2144">[CallerMemberName]</a> استفاده کنیم، پس دیگر نیازی به استفاده از عملگر nameof نخواهد بود. اما تفاوت کلیدی این است که CallerMemberName در زمان اجرا نام فیلد فراخوان را دریافت میکند (run time)، در حالیکه با استفاده از عملگر nameof می‌توانید در زمان کامپایل به نام فیلد دسترسی داشته باشید (compile time). <br/> <br/> </div> </div> <div style="direction: rtl; text-align: right;"> <span style=" white-space: pre;"> <b>محدودیت‌های عملگر nameof</b> </span> </div> <div style="direction: rtl; text-align: right;"> <span style=" white-space: pre;">این عملگر حالت‌هایی را که مشاهده می‌کنید، فعلاً پشتیبانی نخواهد کرد:</span> </div> <div style="direction: rtl; text-align: right;"> <div align="left" dir="ltr" style="direction:ltr;text-align:left;">
<pre language="CSharp" name="code">nameof(f()); // where f is a method - you could use nameof(f) instead&#10;nameof(c._Age); // where c is a different class and _Age is private. Nameof can't break accessor rules.&#10;nameof(List&lt;&gt;); // List&lt;&gt; isn't valid C# anyway, so this won't work&#10;nameof(default(List&lt;int&gt;)); // default returns an instance, not a member&#10;nameof(int); // int is a keyword, not a member- you could do nameof(Int32)&#10;nameof(x[2]); // returns an instance using an indexer, so not a member&#10;nameof("hello"); // a string isn't a member&#10;nameof(1 + 2); // an int isn't a member</pre>
 </div>
 برای آزمایش عملگر nameof می‌توانیم یک تست را در حالت‌های زیر بنویسیم:
 </div> <div style="direction: rtl; text-align: right;"> <br/> </div> <div style="direction: rtl; text-align: right;"> <p style="margin-left: auto; margin-right: auto;"> <img src="/img/dntips/4d97b22dc9ec4e8c244f.jpg" style="display:block; margin-left: auto; margin-right: auto;"/> </p> </div> <div style="direction: rtl; text-align: right;"> <p style="margin-left: auto; margin-right: auto;"> </p> </div> <div style="direction: rtl; text-align: right;"> <p style="margin-left: auto; margin-right: auto;"> </p> </div> <div style="direction: rtl; text-align: right;"> <br/> </div> <div style="direction: rtl; text-align: right;">همانطور که مشاهده می‌کنید، همه‌ی حالت‌های فوق با موفقیت پاس شده‌اند.</div> </div> </div></div>
