مقدمه
در فصل گذشته، دیدیم که برای نوشتن کوئریهای LINQ میتوان از دو سینتکس متفاوت استفاده
کرد: سینتکس کوئری (Query Syntax) که شبیه به SQL است، و
سینتکس متد (Method Syntax) که از زنجیرهی متدهای بسطی استفاده میکند. ما اشاره
کردیم که این دو سینتکس در نهایت معادل یکدیگر هستند. اما این به چه معناست؟ در این درس، پرده از
این "جادو" برداشته و نشان میدهیم که چگونه کامپایلر C#، سینتکس خوانا و اعلانی کوئری
را به فراخوانیهای استاندارد متدهای بسطی ترجمه میکند. درک این فرآیند به شما کمک میکند تا به
درک عمیقتری از نحوهی کار LINQ برسید و بفهمید که LINQ یک زبان جداگانه
نیست، بلکه یکپارچگی هوشمندانهی ویژگیهای زبان C# است.
سینتکس کوئری: یک "شکر نحوی"
در برنامهنویسی، اصطلاح شکر نحوی (Syntactic Sugar) به سینتکسی در یک زبان گفته
میشود که برای سادهتر یا خواناتر کردن یک کار طراحی شده، اما هیچ قابلیت جدیدی به زبان اضافه
نمیکند. در واقع، کامپایلر این سینتکس "شیرین" را به یک ساختار بنیادیتر و معادل ترجمه میکند.
سینتکس کوئری LINQ یک مثال کلاسیک از شکر نحوی است. تمام عبارتهایی که با from ...
in ... where ... select مینویسید، قبل از کامپایل نهایی، توسط کامپایلر C# به
زنجیرهای
از فراخوانی متدهای بسطی (سینتکس متد) تبدیل میشوند.
یک مثال عینی
بیایید یک کوئری کامل را در نظر بگیریم و ببینیم کامپایلر دقیقاً چه کاری با آن انجام میدهد. ما از
همان لیست کارمندان درس قبل استفاده میکنیم.
قدم اول: کدی که ما مینویسیم (سینتکس کوئری)
فرض کنید میخواهیم نام کارمندان دپارتمان "Engineering" را که حقوقی بیش از ۷۵۰۰۰ دارند، پیدا کرده
و بر اساس نامشان مرتب کنیم. ما این کوئری را به صورت زیر مینویسیم:
Program.cs
var querySyntax = from emp in employees
where emp.Department == "Engineering" && emp.Salary > 75000
orderby emp.Name
select emp.Name;
قدم دوم: کدی که کامپایلر تولید میکند (سینتکس متد)
وقتی کامپایلر این کد را میبیند، آن را به طور کامل به سینتکس متد معادل آن ترجمه میکند. کدی که
واقعاً کامپایل و اجرا میشود، به شکل زیر است:
Compiler Translation
var methodSyntax = employees
.Where(emp => emp.Department == "Engineering" && emp.Salary > 75000)
.OrderBy(emp => emp.Name)
.Select(emp => emp.Name);
همانطور که میبینید، نتیجهی نهایی هر دو کد دقیقاً یکسان است. سینتکس کوئری تنها یک راه سادهتر و
خواناتر برای بیان همان زنجیرهی فراخوانی متدهاست.
چرا دو سینتکس وجود دارد و از کدام استفاده کنیم؟
این سوال پیش میآید که اگر هر دو سینتکس یک کار را انجام میدهند، چرا هر دو وجود دارند؟
- سینتکس کوئری (Query Syntax): برای توسعهدهندگانی که با SQL آشنا
هستند، بسیار شهودی و خواناست. این سینتکس برای کوئریهای ساده تا متوسط که شامل فیلتر،
مرتبسازی و پرتاب هستند، عالی عمل میکند.
- سینتکس متد (Method Syntax): این سینتکس قدرتمندتر و انعطافپذیرتر است.
اولاً، تمام عملگرهای LINQ (مانند Count, Take,
FirstOrDefault, Max) معادل
کلمهی کلیدی در سینتکس کوئری را ندارند. برای استفاده از این عملگرها، شما
باید از سینتکس متد استفاده کنید. ثانیاً، زنجیرهسازی متدها برای ساخت
دینامیک کوئریها در کد، سادهتر است.
رویکرد ترکیبی: در عمل، بسیاری از برنامهنویسان از یک رویکرد ترکیبی استفاده
میکنند. آنها بخش اصلی کوئری را با سینتکس کوئری مینویسند و سپس نتیجه را در پرانتز قرار داده و
یک عملگر از سینتکس متد را بر روی آن فراخوانی میکنند.
int count = (from emp in employees
where emp.Department == "Sales"
select emp).Count();
در نهایت، انتخاب بین این دو سینتکس به سلیقهی شخصی و خوانایی کد در آن سناریوی خاص بستگی دارد.
مهم این است که بدانید هر دو در نهایت به یک چیز تبدیل میشوند.