مدخل إلى تعابير Lambda واستعلامات Linq في لغة سي شارب #C

تعتبر تقنيّة Linq من التقنيّات الجديدة نسبيًّا في سي شارب ولغات دوت نت عمومًا. تسمح هذه التقنيّة بإجراء عمليّات استعلام معقّدة لاستخلاص البيانات بشكل سلس وسهل بسبب شكلها المألوف كما سنرى لاحقًا في هذا الدرس.

لتقنيّة Linq أشكال متعدّدة:
- Linq to Objects: للتعامل مع البيانات الموجودة في ذاكرة البرنامج.
- Linq To XML: للتعامل مع البيانات النصيّة الموجودة بتنسيق XML.
- Linq To SQL: وهي تقنيّة خاصّة بالحصول على البيانات من خادم SQL Server. في الحقيقة تمّ التخلّي عن هذه التقنيّة رغم حداثتها، وذلك لصالح تقنيّة أحدث وأكثر تطوّرًا وهي Entity Framework.
كما يتحدّث هذا الدرس عن تعابير Lambda وهي من المزايا المفيدة والتي تسهّل عمل المبرمجين إلى حدٍّ كبير. ستناول في هذا الدرس الشكل الأوّل من Linq، وهو استخدام Linq مع الكائنات Objects. ولكن قبل ذلك لنتحدّث قليلًا عن تعابير Lambda.
تعابير Lambda
تستطيع تخيّل تعابير Lambda على أنّها دوال functions صغيرة ليس لها اسم، تعمل على إجراء عمليّات حسابيّة بسيطة، ومن الممكن أن ترجع نتيجة. في الواقع يمكن للنوّاب Delegates أن تغلّف تعابير Lambda ضمن شروط محدّدة. سنتناول مثالًا بسيطًا يوضّح كيفيّة التعامل معها. انظر إلى الشيفرة التالية:
class Program { delegate int Square(int x); static void Main(string[] args) { Square square = (x) => x * x; int result = square(5); } }
صرّحنا في الشيفرة السابقة عن النائب Square الذي يتطلّب وسيطًا واحدًا من النوع int ويُرجع قيمة من نفس النوع. يُفترض بهذا النائب بأن يُغلّف التوابع التي تعمل على إيجاد مربّع عدد صحيح. إذا نظرت الآن إلى التابع Main ستجد أنّنا في السطر الأوّل منه نصرّح عن المتغيّر square من نوع النائب Square، حيث نُسند إليه ما يلي:
(x) => x * x
التعبير السابق هو تعبير Lambda بسبب وجود السهم <= ضمنه. فهم هذا التعبير بسيط، فهو يطلب وسيطًا وحيدًا (x) على يسار السهم، ويضرب قيمة هذا الوسيط بنفسها: x * x على يمين السهم، سيُرجع هذا التعبير قيمة x مضروبةً بنفسها. ولكن الملفت في الأمر أنّنا قد أسندنا هذا التعبير إلى متغيّر من نوع النائب Square. السبب في ذلك أنّ تعبير Lambda السابق يتوافق مع النائب Square في أنّه يحتاج إلى وسيط وحيد من النوع int ويُرجع قيمة من نفس النوع. ولكنّنا لم نوضّح في تعبير Lambda نوع الوسيط أو نوع القيمة المُعادة! لا مشكلة في ذلك، فسيتم استخلاص النوع من الوسيط المُمرّر وذلك بشكل تلقائي.
كمثال آخر على استخدام تعبير Lambda يمكن كتابة تعبير يتطلّب وسيطين ولكن لا يُرجع أي قيمة. انظر إلى الشيفرة التالية:
class Program { delegate void SumAndPrinting(int a, int b); static void Main(string[] args) { SumAndPrinting sumAndPrnt = (a, b) => Console.WriteLine(a + b); sumAndPrnt(3, 4); } }
النائب SumAndPrinting يقبل الآن وسيطين من النوع int لكنّه لا يُرجع أي قيمة (void). انظر إلى تعبير Lambda كيف أصبح:
(a, b) => Console.WriteLine(a + b)
لاحظ كيف أنّ الوسائط الموجودة بين قوسين تفصل بينها فواصل عاديّة دون تحديد الأنواع. كما يمكنك أن تلاحظ أيضًا بأنّ هذا التعبير مهمّته جمع قيمتي الوسيطين والطبع إلى الشاشة دون إرجاع أيّ قيمة.
ملاحظة: يمكننا الاستغناء عن القوسين في تعبير Lambda، إذا أردنا تمرير وسيط واحد فقط. مثل:
x => x * x
استعلاماتLinq
للاستفادة من Linq يجب إضافة نطاق الاسم System.Linq باستخدام الكلمة المحجوزة using. أفضل وسيلة لفهم Linq هي من خلال مثال تطبيقي بسيط، في البرنامج Lesson15_01 سنستخدم الصنف Student الذي استخدمناه في درس سابق ولكن سنجري فيه بعض التعديلات البسيطة، حيث أصبحنا نفصل اسم الطالب FirstName عن كنيته LastName، بالإضافة إلى إضافة حقل جديد اسمه Id من النوع int، والذي يُعبّر عن رقم الطالب:
class Student { public int Id { get; set; } public string FirstName { get; set; } public string LastName { get; set; } public int Mark { get; set; } }
سننشئ 10 كائنات من الصنف Student ونخزّنها ضمن مجموعة عموميّة نفّذ البرنامج السابق لتحصل على شكل شبيه بما يلي: لاحظ كيف استثنى البرنامج في القائمة الثانية الطلاب الذين تقل درجاتهم عن 60 أو تساويها. قارن بين القائمتين واكتشف العناصر المستثناة. يبدأ البرنامج في التابع Main بإنشاء 10 كائنات من النوع Student تمثّل بيانات عشرة طلّاب وإسناد هذه الكائنات فورًا إلى المجموعة القائمة studentsList بشكل مختصر (الأسطر من 19 إلى 31). الملفت هنا هو طريقة إنشاء كل من هذه الكائنات. انظر إلى السطر 21 مثلًا: هذا شكل مختصر لإنشاء كائن من النوع Student حيث استخدمنا حاضنة {} بعد اسم الصنف Student مباشرةً وكتبنا أسماء الخصائص التي نريد تهيئتها ضمن هذه الحاضنة. بالنسبة لبانيّة الصنف Student فستُستدعى بكلّ تأكيد. يعتبر هذا الشكل من الإنشاء والإسناد المباشر للخصائص مفيدًا للغاية (أستخدمه بكثرة في برامجي الخاصّة) حيث يقلّل من أسطر الشيفرة البرمجيّة إلى حدٍّ كبير. سيطبع البرنامج بعد ذلك القائمة التي أنشأناها قبل قليل من باب التوضيح، وذلك من خلال استدعاء التابع الساكن PrintList (السطر 35) بالشكل التالي: مرّرنا لهذا التابع القائمة الكاملة studentsList. التصريح عن التابع الساكن موجود في الأسطر بين 48 و 56 وسنتكلّم عنه بعد قليل. يحتوي السطر 38 على عبارة برمجيّة تستخدم استعلام Linq: يقع استعلام Linq على يمين عامل الإسناد (=)، وفي الحقيقة إذا كان لديك اطّلاع على لغة SQL فسيكون هذا الاستعلام مألوفًا بالنسبة إليك. لنركّز الآن على هذا الاستعلام فحسب: يبدأ الاستعلام بالكلمة المحجوزة from يتبعه اسم متغيّر جديد يمكنك تسميّته بأيّ اسم ترغبه. اخترت الاسم student لأنّني وجدتّه معبّرًا. بعد اسم المتغيّر الجديد نجد الكلمة المحجوزة in وبعدها اسم المجموعة التي نريد تطبيق الاستعلام عليها. إذًا أصبح بإمكاننا قراءة السطر الأوّل من الاستعلام على الشكل التالي: اقتباس “من أجل كل عنصر student موجود ضمن المجموعة studentsList”. يبدأ السطر الثاني بالكلمة المحجوزة where وهي اختياريّة ومن الممكن عدم كتابتها، وهي تسمح بكتابة شرط من ممكن تطبيقه على عناصر المجموعة studentsList. بالنسبة لمثالنا هذا، اخترت تطبيق الشرط: أي أنّني أريد أن تكون درجة كل طالب (student) أكبر تمامًا من 60. أمّا السطر الثالث select student فهو يخبر Linq عن شكل البيانات التي نريد الحصول عليها بنتيجة تنفيذ الاستعلام. في مثالنا هذا نريد الحصول على مجموعة كل عنصر من عناصرها هو كائن من النوع Student. بنتيجة تنفيذ الاستعلام السابق سيحتوي المتغيّر students على مرجع لكائن مجموعة يحقّق الواجهة يمكن لاستعلام Linq أن يُنتج مرجعًا لكائن مجموعة يحقّق الواجهة في الواقع يمكن استخدام شروط أكثر تعقيدًا كأن نرغب بالحصول على جميع الطلّاب الذين تتراوح درجاتهم بين 60 و90 ضمنًا على سبيل المثال، وذلك باستخدام العامل && بالشكل التالي: كما من الممكن أنّ نرتّب البيانات حسب رقم الطالب id، أو بحسب اسمه FirstName أو كنيته LastName أو بمزيج منها، وذلك باستخدام الكلمة المحجوزة orderby الخاصّة بـ Linq: سيقوم الاستعلام السابق بترتيب العناصر التي توافق الشرط الموجود في القسم where حسب الاسم ثمّ حسب الكنيّة. توجد في الحقيقة الكثير من المزايا القويّة التي تتمتّع بها استعلامات Linq والتي لا يتّسع هذا الدرس لذكرها. بالنسبة للتابع PrintList (الأسطر من 50 حتى 58) فيقتصر دوره على طباعة جدول للقائمة التي نمرّرها كوسيط إليه. لاحظ أنّ الوسيط الوحيد الذي يقبله يحقّق الواجهة هل تريد المزيد من الإثارة؟ أضف السطر التالي إلى السطر 43 من البرنامج السابق (أي بعد العبارة التي تستخدم استعلام Linq): تستخدم هذه العبارة التابع Average من المتغيّر students الذي يحتوي على قائمة الطلّاب بعد التصفيّة كما نعلم. وكما يُوحي اسمه يعمل هذا التابع على حساب معدّل الطلاب (كائنات Student) الموجودين ضمن students. ولكن كيف سيعرف التابع Average الحقل الذي سيتمّ بموجبه حساب المعدّل؟ يتمثّل الحل في استخدام تعبير Lambda يتطلّب وسيطًا واحدًا (الوسيط s) الذي سيمثّل كائن Student، ويُرجع قيمة الخاصيّة Mark له: سيستخدم التابع هذا التعبير للمرور على جميع العناصر الموجودة ضمن المجموعة students ليحصل على درجة كلّ منها باستخدام تعبير Lambda السابق ثمّ يحسب المعدّل، ليعمل البرنامج على إسناده إلى المتغيّر average وهو من النوع double كما هو واضح. بعد تنفيذ العبارة السابقة وعلى فرض أنّ نسخة البرنامج Lesson15_01 الأساسيّة هي التي استُخدمت، ستكون قيمة average تساوي 77.5، ويمثّل هذا الرقم معدّل الطلاب الذين تكون درجاتهم أكبر تمامًا من 60. قد يبدو كلّ ما قدّمناه جميلًا وممتعًا، لكنّك لن تستمتع بشكل فعليّ بهذه المزايا الرائعة التي توفّرها Linq و تعابير Lambda ما لم تستخدمها في برامجك الخاصّة. أستخدم مثل هذه المزايا في برامجي التي أطوّرها، ولن تتصوّر مدى سعادتي عندما أستخلص بيانات من قاعدة بيانات أو من خدمة ويب web service قد تحتوي على المئات أو الآلاف من البيانات الخام، ثمّ أُطبّق عليها وصفات Linq السحريّة فأحصل على ما أريده بكتابة عبارة برمجيّة واحدة فقط! أجرِ تعديلًا على البرنامج Lesson15_01 بحيث نحصل على جميع الطلّاب الذين تكون درجاتهم أقل تمامًا من 50. أجرِ تعديلًا آخرًا على البرنامج Lesson15_01 بحيث نحصل على جميع الطلّاب الذين يكون الحرف الأوّل من اسمهم هو "A". (تلميح: أحد الحلول المقترحة هو استخدام التابع StartWith من الخاصيّة النصية FirstName للكائن student أي على الشكل التالي: وذلك بعد الكلمة where في استعلام Linq ). تعرّفنا في هذا الدرس على تعابير Lambda واستعلامات Linq. حيث صمّمنا عدّة برامج توضّح هاتين التقنيّتين المهمّتين في البرمجة باستخدام سي شارب. ستصادف كلًّا منهما كثيرًا في حياتك البرمجيّة، وستكون سعيدًا باستخدامها نظرًا للاختصار الكبير الذي ستحصل عليه في الشيفرة البرمجيّة، هذا فضلًا عن الأداء عالي المستوى الذي لن تستطيع مجاراته باستخدامك للشيفرة التقليديّة.
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 5 namespace Lesson15_01 6 { 7 class Student 8 { 9 public int Id { get; set; } 10 public string FirstName { get; set; } 11 public string LastName { get; set; } 12 public int Mark { get; set; } 13 } 14 15 class Program 16 { 17 static void Main(string[] args) 18 { 19 List
new Student {Id = 1, FirstName = "Ahmad", LastName = "Morad" , Mark = 80}
PrintList(studentsList);
IEnumerable
from student in studentsList where student.Mark > 60 select student
where student.Mark > 60
from student in studentsList where student.Mark >= 60 && student.Mark <= 90 select student
from student in studentsList where student.Mark >= 60 && student.Mark <= 90 orderby student.FirstName, student.LastName select student
double average = students.Average(s => s.Mark);
s => s.Mark
تمارين داعمة
تمرين 1
تمرين 2
student.FirstName.StartsWith("A")
الخلاصة


%%
my site; Seo prices
%%
Here is my web site :: online roulette (spoolfabricshop.com)
%%
Take a look at my site; gambling (Zita)
%%
Feel free to surf to my web page – experience (Jared)
%%
Also visit my web blog: best (Samaragardenandhome.com)
%%
my site :: gamble online (https://neopoets.Org/)
%%
Also visit my web blog: Online Gambling; Thelordschips.Org,
%%
my homepage :: play casino online [greenwichseniorrecruitment.com]
%%
Also visit my blog post Gamble Online [Vivabemonline.Com]
%%
my blog :: Online Gambling (Tempussuisse.Com)
%%
Here is my website: Sports, https://Theconservativemonster.Com,
%%
my blog: Blackjack (Chinarchitect.Com)
%%
my page :: Online casino (https://billwilsonmsp.org/)
%%
Feel free to surf to my web-site – betting – Hellodesignsugar.Com,
%%
Also visit my website; bet – https://theartofheathersinn.com –
%%
Here is my blog … bet on sports (Christinamaury.com)
%%
Here is my web-site: blackjack (doylegrisham.Com)
%%
Stop by my webpage; Sports betting [https://innovationalsteps.org]
%%
my blog post Online Poker (https://Balltire-Automotive.Com)
%%
Also visit my site; Live (https://onlyballingame.com/)
%%
Review my blog post: online roulette (Alejandrina)
%%
my blog post … live (chiangmaiplan.com)
%%
My website bet (Jeanna)
%%
Here is my web-site: sports – https://dresslp.com,
%%
Feel free to visit my blog post: gambling addiction – https://rimonberkshires.org –
%%
my site … Experience (https://Nedvizhimost-Na-Tenerife.Com/)
%%
Also visit my web site – sports Betting (https://stronghillrestaurant.com)
%%
Also visit my page :: gambling addiction (Rico)
%%
Review my website blackjack, https://jawkwardlol.com,
%%
Also visit my webpage: blackjack – countdowntokannaway.Com,
%%
Here is my web blog; bet (huntermacros.org)
%%
Also visit my webpage; Gambler (Lickids.Com)
%%
Feel free to visit my web-site; Sports Betting, https://Nuclearjustice.Org/,
%%
Here is my web page: Online casino (https://Standupphilosophy.net)
%%
Feel free to surf to my web page … Online Roulette – Myuncleswedding.Com –
%%
Feel free to visit my web page horse Betting [spchospital.org]
%%
Feel free to surf to my page :: Online, thedirtdrifters.com,
%%
Have a look at my web site – Seo Pricing
%%
Also visit my blog post; cbd Prefilled Carts
%%
my homepage – seo pricing packages
fkuq36
Your point of view caught my eye and was very interesting. Thanks. I have a question for you. https://www.binance.com/register?ref=JW3W4Y3A
Your article helped me a lot, is there any more related content? Thanks! https://www.binance.bh/register?ref=IHJUI7TF
I don’t think the title of your article matches the content lol. Just kidding, mainly because I had some doubts after reading the article. https://www.binance.bh/futures/ref?code=QCGZMHR6
Just discovered this gem and I am really impressed with the game selection. The slots have amazing graphics and the bonuses keep coming. Logging in is super easy and the interface feels very professional. Definitely my new go to place for some fun online action. inwa777login
I have been looking for a reliable platform that actually delivers on its promises and this one checks every box for me. The interface is clean, the games are thrilling, and my winnings always arrive right on schedule. It is rare to find a place that balances entertainment with genuine transparency so well. mymillion888
The slot library here is absolutely packed with my favorite classics and fresh releases. Bonus triggers feel fair and the payout speed is something I have never seen elsewhere. I keep coming back just for the reliable vibes. goldbetslot
Thank you for your sharing. I am worried that I lack creative ideas. It is your article that makes me full of hope. Thank you. But, I have a question, can you help me? https://accounts.binance.bh/uk-UA/register-person?ref=XZNNWTW7
Your point of view caught my eye and was very interesting. Thanks. I have a question for you.
I don’t think the title of your article matches the content lol. Just kidding, mainly because I had some doubts after reading the article. https://www.binance.com/futures/ref?code=W49FLGDN