اندازهی قلم متن
تخمین مدت زمان مطالعهی مطلب:
پنج دقیقه
در مطلب «روش بازگشت به قالبهای کلاسیک پروژهها در دات نت 6» مشاهده کردیم که قالب پیشفرض یک برنامهی کنسول دات نت 6، چنین فایل Program.cs ای را تولید میکند:
که در حقیقت همان اجبار به استفادهی از سبک «Top Level Programs» ارائه شدهی در C# 9.0 است. اما اگر به همین دو سطر هم دقت کنید، یک تفاوت مهم را با نمونهی C# 9.0 دارد و آن هم عدم ذکر عبارت using System در ابتدای آن است. علت اینجا است که فایل csproj پیشفرض پروژههای مبتنی بر NET 6.0.، دو تغییر مهم دیگر را هم دارند:
الف) فعال بودن nullable reference types که در C# 8.0 ارائه شد.
ب) فعال بودن ImplicitUsings که مختص به C# 10.0 است.
بررسی مفهوم global using directives در C# 10.0
هدف اصلی از وجود Using directives در زبان #C که از نگارش 1 آن در دسترس هستند، خلاصه نویسی نام طولانی اشیاء و متدها است. برای مثال نام اصلی متد Console.WriteLine به صورت System.Console.WriteLine است که با درج فضای نام System در ابتدای فایل، میتوان از ذکر مجدد آن جلوگیری کرد. از این دست میتوان به نوع System.Collections.Generic.List نیز اشاره کرد که کمتر کسی علاقمند است تا این نام طولانی را تایپ کند. به همین جهت با استفاده از یک using directive متناظر با فضای نام System.Collections.Generic، ذکر نام این نوع، به List خلاصه میشود.
طراحی دات نت 6 مبتنی بر سبک minimalism است! برای نمونه خلاصه کردن نزدیک به 10 سطر فایل Program.cs کلاسیک، به تنها یک سطر که به همراه ذکر using System در ابتدای آن هم نیست. در C# 10.0 دیگر نیازی نیست تا برای مثال ذکر using System را در دهها و یا صدها فایل، بارها و بارها تکرار کرد. برای اینکار تنها کافی است یکبار آنرا به صورت global تعریف کنیم و پس از آن دیگر نیازی به ذکر آن در کل پروژه نیست:
میتوان این سطر را در ابتدای یک تک فایل cs. قرار داد و ذکر آن به معنای الحاق خودکار آن، در ابتدای تک تک فایلهای cs. برنامه است.
چند نکته:
- امکان ترکیب global usingها و usingها معمولی در یک فایل هست.
- امکان تعریف global usingهای استاتیک نیز پیشبینی شدهاست:
که برای نمونه در این حالت بجای ذکر Console.WriteLine، تنها ذکر نام متد WriteLine در سراسر برنامه کفایت میکند.
مفهوم جدید implicit global using directives در C# 10.0 و به کمک NET SDK 6.0.
تا اینجا دریافتیم که میتوان دایرکتیوهای سراسری using را در برنامه به صورت دستی تعریف و استفاده کرد. اما ... پروژهی کنسولی که به صورت پیشفرض توسط NET SDK 6.0. ایجاد میشود، به همراه هیچ global using ای نیست. این مورد توسط تنظیم زیر که جزئی از NET SDK 6.0. است، فعال میشود:
زمانیکه ImplicitUsings را در فایل csproj برنامه فعال میکنیم، یعنی قرار است از یکسری global usingهای از پیش تعریف شدهی توسط SDK استفاده کنیم. بنابراین «global using directives» جزئی از ویژگیهای جدید C# 10.0 است اما « implicit global using directives» تنها یک لطف ارائه شدهی توسط NET SDK. است. برای یافتن لیست آنها، پروژه را build کرده و سپس به پوشهی obj\Debug\net6.0 مراجعه کنید. در اینجا به دنبال فایلی مانند MyProjectName. GlobalUsings.g.cs بگردید. محتویات آن به صورت زیر است:
اینها همان global using هایی هستند که با فعالسازی تنظیم ImplicitUsings در فایل csproj، به صورت خودکار توسط NET SDK. تولید و به برنامه الحاق میشوند.
البته این فایل ویژه به ازای نوعهای پروژههای مختلف، محتوای متفاوتی را دارد. برای مثال در برنامههای ASP.NET Core، چنین محتوای پیشفرضی را پیدا میکند:
این تعاریف در اصل در پوشهی C:\Program Files\dotnet\sdk\6.0.100-rc.2.21505.57\Sdks\Microsoft.NET.Sdk\targets و در فایل Microsoft.NET.GenerateGlobalUsings.targets آن قرار دارند.
روش حذف و یا اضافهی global usingهای پیشفرض
اگر به هر دلیلی نمیخواهید تعدادی از global usingهای پیشفرض به همراه گزینهی ImplicitUsings استفاده کنید، میتوانید آنها را در فایل csproj به صورت زیر، Remove و یا حتی موارد جدیدی را Include کنید:
یکی از کاربردهای این قابلیت، تولید کتابخانههای multi-target است که میتوان توسط Conditionها، فضاهای نامی را که نباید برای target خاصی include کرد، مشخص نمود:
// See https://aka.ms/new-console-template for more information Console.WriteLine("Hello, World!");
<Project Sdk="Microsoft.NET.Sdk"> <PropertyGroup> <OutputType>Exe</OutputType> <TargetFramework>net6.0</TargetFramework> <ImplicitUsings>enable</ImplicitUsings> <Nullable>enable</Nullable> </PropertyGroup> </Project>
ب) فعال بودن ImplicitUsings که مختص به C# 10.0 است.
بررسی مفهوم global using directives در C# 10.0
هدف اصلی از وجود Using directives در زبان #C که از نگارش 1 آن در دسترس هستند، خلاصه نویسی نام طولانی اشیاء و متدها است. برای مثال نام اصلی متد Console.WriteLine به صورت System.Console.WriteLine است که با درج فضای نام System در ابتدای فایل، میتوان از ذکر مجدد آن جلوگیری کرد. از این دست میتوان به نوع System.Collections.Generic.List نیز اشاره کرد که کمتر کسی علاقمند است تا این نام طولانی را تایپ کند. به همین جهت با استفاده از یک using directive متناظر با فضای نام System.Collections.Generic، ذکر نام این نوع، به List خلاصه میشود.
طراحی دات نت 6 مبتنی بر سبک minimalism است! برای نمونه خلاصه کردن نزدیک به 10 سطر فایل Program.cs کلاسیک، به تنها یک سطر که به همراه ذکر using System در ابتدای آن هم نیست. در C# 10.0 دیگر نیازی نیست تا برای مثال ذکر using System را در دهها و یا صدها فایل، بارها و بارها تکرار کرد. برای اینکار تنها کافی است یکبار آنرا به صورت global تعریف کنیم و پس از آن دیگر نیازی به ذکر آن در کل پروژه نیست:
global using System;
چند نکته:
- امکان ترکیب global usingها و usingها معمولی در یک فایل هست.
- امکان تعریف global usingهای استاتیک نیز پیشبینی شدهاست:
global using static System.Console;
مفهوم جدید implicit global using directives در C# 10.0 و به کمک NET SDK 6.0.
تا اینجا دریافتیم که میتوان دایرکتیوهای سراسری using را در برنامه به صورت دستی تعریف و استفاده کرد. اما ... پروژهی کنسولی که به صورت پیشفرض توسط NET SDK 6.0. ایجاد میشود، به همراه هیچ global using ای نیست. این مورد توسط تنظیم زیر که جزئی از NET SDK 6.0. است، فعال میشود:
<ImplicitUsings>enable</ImplicitUsings>
// <auto-generated/> global using global::System; global using global::System.Collections.Generic; global using global::System.IO; global using global::System.Linq; global using global::System.Net.Http; global using global::System.Threading; global using global::System.Threading.Tasks;
البته این فایل ویژه به ازای نوعهای پروژههای مختلف، محتوای متفاوتی را دارد. برای مثال در برنامههای ASP.NET Core، چنین محتوای پیشفرضی را پیدا میکند:
// <autogenerated /> global using global::System; global using global::System.Collections.Generic; global using global::System.IO; global using global::System.Linq; global using global::System.Net.Http; global using global::System.Threading; global using global::System.Threading.Tasks; global using global::System.Net.Http.Json; global using global::Microsoft.AspNetCore.Builder; global using global::Microsoft.AspNetCore.Hosting; global using global::Microsoft.AspNetCore.Http; global using global::Microsoft.AspNetCore.Routing; global using global::Microsoft.Extensions.Configuration; global using global::Microsoft.Extensions.DependencyInjection; global using global::Microsoft.Extensions.Hosting; global using global::Microsoft.Extensions.Logging;
روش حذف و یا اضافهی global usingهای پیشفرض
اگر به هر دلیلی نمیخواهید تعدادی از global usingهای پیشفرض به همراه گزینهی ImplicitUsings استفاده کنید، میتوانید آنها را در فایل csproj به صورت زیر، Remove و یا حتی موارد جدیدی را Include کنید:
<ItemGroup> <Import Remove="System.Threading" /> <Import Include="Microsoft.Extensions.Logging" /> </ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net472'"> </ItemGroup>