دلیل اصلی اینکه در Dependency Injection (DI) از private readonly استفاده میکنیم و نه const، فراتر از «زمان اجرا در مقابل زمان کامپایل» است. مهمترین دلایل عبارتند از:
۱. ماهیت متغیرها (Reference Type در مقابل Value Type)
constفقط برای مقادیر ثابت و ساده (مانند اعداد، رشتهها، bool) در زمان کامپایل قابل استفاده است.- سرویسهایی که از طریق DI تزریق میشوند، اشیاء (Reference Type) هستند مانند
IMyService،ILogger،DbContextو غیره. - امکان تعریف
constبرای یک شیء وجود ندارد چون آدرس شیء در حافظه تا زمان اجرا مشخص نمیشود.
۲. مقداردهی با سازنده (Constructor Injection)
readonlyبه ما اجازه میدهد که فیلد را درون سازنده مقداردهی کنیم (که دقیقاً همان جایی است که DI تزریق انجام میشود).constاجازه مقداردهی در سازنده را نمیدهد و باید مقدار آن سرخط (compile-time) مشخص باشد.
۳. تغییرناپذیری (Immutability) و امنیت
private readonlyتضمین میکند که بعد از خروج از سازنده، هیچکس (حتی خود کلاس) نتواند این فیلد را تغییر دهد.- این یعنی وابستگی شما ثابت و امن میماند و کسی نمیتواند به اشتباه یا عمداً آن را عوض کند.
constاین قابلیت را ندارد و فقط برای مقادیر بیتغییر ابتدایی کاربرد دارد.
۴. تستپذیری (Testability)
- با
readonlyمیتوانید در هنگام تست، یک Mock یا Stub از سرویس را به سازنده بدهید. - با
constچنین امکانی وجود ندارد چون نمیتوانید یک شیء را به عنوان ثابت تعریف کنید.
۵. طول عمر و مدیریت حافظه
- فیلد
readonlyیک ارجاع به شیء تزریقشده نگه میدارد و این شیء توسط GC مدیریت میشود. constدر کد کامپایل شده به صورت مقدار درج (inline) میشود و ربطی به مدیریت حافظه اشیاء ندارد.
خلاصه نهایی:
ما از private readonly استفاده میکنیم، نه به خاطر زمان اجرا بودن، بلکه چون:
- سرویسها شیء هستند و
constبرای اشیاء مجاز نیست. - باید مقدار را در سازنده دریافت کنیم.
- میخواهیم فیلد غیرقابل تغییر باشد تا از دستکاری تصادفی جلوگیری کنیم.
- میخواهیم تستپذیری و DI به درستی کار کند.
const به هیچوجه جایگزین مناسبی برای نگهداری وابستگیهای تزریقی نیست، حتی اگر مقدار آن در زمان کامپایل مشخص بود.