Expression<Func<T>> बनाम Func<T>: C# में ऑप्टिमाइज़ेशन का रहस्य

शुरुआती लोगों के लिए ऑनलाइन Python प्रशिक्षक

Python आसानी से सीखें बिना सिद्धांत के बोझ के। स्वचालित जांच के साथ व्यावहारिक कार्य हल करें और ब्राउज़र में सीधे कोड लिखें।

पाठ्यक्रम शुरू करें

Expression\n\n

कल्पना करें: आप C# कोड लिख रहे हैं। आपको किसी विधि में फ़िल्टरिंग शर्त पास करनी है। क्या चुनें: Func<User, bool> या Expression<Func<User, bool>>? लगता है अंतर न्यूनतम है — दोनों एक उपयोगकर्ता लेते हैं और bool लौटाते हैं। लेकिन पर्दे के पीछे अंतरों का एक पूरा ब्रह्मांड छिपा है।

\n\n

Stack Overflow पर इस प्रश्न को हज़ारों बार देखा गया है — और यह उचित भी है। आज हम समझेंगे कि क्यों Expression<Func<T>> सामान्य Func<T> से अधिक शक्तिशाली, तेज़ और सुरक्षित हो सकता है। और सबसे महत्वपूर्ण बात — प्रत्येक का उपयोग कब करें, ताकि खुद को नुकसान न पहुँचे।

\n\n

संक्षिप्त परिचय: Func और Expression क्या हैं?

\n\n

Func<T> बस एक डेलिगेट है। निष्पादन के लिए तैयार एक फ़ंक्शन, संकलित मशीन कोड। आप इसे डेटा देते हैं — यह उसे प्रोसेस करता है। तेज़, कुशल, लेकिन… अपारदर्शी।

\n\n
Func<User, bool> isAdult = user => user.Age >= 18;\nbool result = isAdult(someUser); // तुरंत निष्पादित होता है
\n\n

Expression<Func<T>> एक एक्सप्रेशन ट्री है। कोड नहीं, बल्कि उसका विवरण। आप इसे सीधे कॉल नहीं कर सकते — आपको या तो इसे डेलिगेट में संकलित करना होगा (.Compile() के माध्यम से), या इसकी संरचना का विश्लेषण करना होगा।

\n\n
Expression<Func<User, bool>> expr = user => user.Age >= 18;\n// सीधे कॉल नहीं कर सकते: expr(someUser) — संकलन त्रुटि\nvar compiled = expr.Compile();\nbool result = compiled(someUser); // अब संभव है
\n\n

लगता है, अनावश्यक झंझट क्यों? लेकिन यही "वर्णनात्मकता" जादू का दरवाजा खोलती है।

\n\n

परिदृश्य 1: LINQ to Objects (मेमोरी में कार्य)

\n\n

जब आप मेमोरी में संग्रह (जैसे List<T>) के साथ काम करते हैं, LINQ to Objects Func<T> का उपयोग करता है। यहाँ एक्सप्रेशन ट्री की आवश्यकता नहीं है — सब कुछ उसी प्रक्रिया में निष्पादित होता है।

\n\n
var users = new List<User>();\nvar adults = users.Where(u => u.Age >= 18).ToList(); // Func<User, bool>
\n\n

प्रदर्शन उत्कृष्ट है: ट्री को पार्स करने का कोई ओवरहेड नहीं। यदि आप केवल स्थानीय डेटा के साथ काम कर रहे हैं — बेझिझक Func का उपयोग करें। यह तेज़ और सरल है।

\n\n

परिदृश्य 2: LINQ to SQL / Entity Framework (डेटाबेस के साथ कार्य)

\n\n

यहाँ जादू शुरू होता है। जब आप लिखते हैं:

\n\n
var adults = dbContext.Users.Where(u => u.Age >= 18).ToList();
\n\n

Entity Framework आपके C# कोड को निष्पादित नहीं करता है। इसके बजाय, यह पारित एक्सप्रेशन ट्री का विश्लेषण करता है और इसे SQL क्वेरी में बदलता है:

\n\n
SELECT * FROM Users WHERE Age >= 18
\n\n

यदि आप Func पास करते, तो EF "अंदर देख" नहीं पाता — यह बस तालिका से सभी उपयोगकर्ताओं को लोड करता और मेमोरी में फ़िल्टर करता। कल्पना करें: 10 मिलियन रिकॉर्ड वाली तालिका — और वे सभी नेटवर्क पर आपके एप्लिकेशन में आते हैं ताकि क्लाइंट पर फ़िल्टर हो सकें।

\n\n

Expression<Func<T>> EF (या किसी अन्य IQueryable प्रदाता) को आपकी शर्त पढ़ने, इसे डेटाबेस की भाषा (SQL, MongoDB query, OData, आदि) में अनुवाद करने और सर्वर पर फ़िल्टरिंग करने की अनुमति देता है।

\n\n

प्रदर्शन: बेंचमार्क और वास्तविक आंकड़े

\n\n

आइए आंकड़ों पर नज़र डालें। एक सरल उदाहरण लें: आयु के अनुसार 100,000 उपयोगकर्ताओं को फ़िल्टर करना।

\n\n
// विकल्प 1: Func — सभी लोड करें, मेमोरी में फ़िल्टर करें\nvar allUsers = dbContext.Users.ToList(); // SELECT * FROM Users\nvar adults1 = allUsers.Where(u => u.Age >= 18).ToList();\n\n// विकल्प 2: Expression — सर्वर पर फ़िल्टर करें\nvar adults2 = dbContext.Users.Where(u => u.Age >= 18).ToList(); // SELECT * FROM Users WHERE Age >= 18
\n\n

परिणाम (अनुमानित, लेकिन संकेतात्मक):

\n
    \n

ब्लॉग

पुस्तक अनुशंसाएँ