C # में प्रतिनिधियों का आपका क्या उपयोग है?
C # में प्रतिनिधियों का आपका क्या उपयोग है?
जवाबों:
अब जब हमारे पास C # में लैम्बडा एक्सप्रेशन और अनाम विधियाँ हैं, तो मैं डेलिगेट्स का बहुत अधिक उपयोग करता हूँ। C # 1 में, जहां आपके पास तर्क को लागू करने के लिए हमेशा एक अलग विधि होनी चाहिए, एक प्रतिनिधि का उपयोग करना अक्सर समझ में नहीं आता है। इन दिनों मैं प्रतिनिधियों का उपयोग करता हूं:
प्रतिनिधि कई उद्देश्यों के लिए बहुत उपयोगी होते हैं।
ऐसा ही एक उद्देश्य डेटा के अनुक्रमों को फ़िल्टर करने के लिए उनका उपयोग करना है। इस उदाहरण में आप एक विधेय प्रतिनिधि का उपयोग करेंगे जो एक तर्क को स्वीकार करता है और प्रतिनिधि के कार्यान्वयन के आधार पर सही या गलत रिटर्न देता है।
यहाँ एक मूर्खतापूर्ण उदाहरण दिया गया है - मुझे यकीन है कि आप इससे कुछ अधिक उपयोगी निकाल सकते हैं:
using System;
using System.Linq;
using System.Collections.Generic;
class Program
{
static void Main()
{
List<String> names = new List<String>
{
"Nicole Hare",
"Michael Hare",
"Joe Hare",
"Sammy Hare",
"George Washington",
};
// Here I am passing "inMyFamily" to the "Where" extension method
// on my List<String>. The C# compiler automatically creates
// a delegate instance for me.
IEnumerable<String> myFamily = names.Where(inMyFamily);
foreach (String name in myFamily)
Console.WriteLine(name);
}
static Boolean inMyFamily(String name)
{
return name.EndsWith("Hare");
}
}
static Boolean inMyFamily(String name)
विधि प्रतिनिधि है। जहां एक प्रतिनिधि को एक पैरामीटर के रूप में लिया जाता है। चूँकि प्रतिनिधि केवल कार्य बिंदु होते हैं, जब आप उस विधि का नाम पास करते हैं .Where(delegate)
जो प्रतिनिधि बन जाता है। चूँकि inMyFamily एक बूलियन प्रकार देता है, इसे वास्तव में एक विधेय माना जाता है। विधेय केवल प्रतिनिधि हैं जो बूलियन्स लौटाते हैं।
एक और दिलचस्प जवाब मिला:
एक सहकर्मी ने मुझसे सिर्फ यह सवाल पूछा - .NET में प्रतिनिधियों का क्या मतलब है? मेरा उत्तर बहुत छोटा था और एक ऐसा जिसे उसने ऑनलाइन नहीं पाया था: एक विधि के निष्पादन में देरी के लिए।
स्रोत: LosTechies
जैसे LINQ कर रहा है।
आप फ़ंक्शन-टाइप किए गए चर और मापदंडों को घोषित करने के लिए प्रतिनिधियों का उपयोग कर सकते हैं।
उदाहरण
"संसाधन उधार" पैटर्न पर विचार करें। आप किसी संसाधन के निर्माण और सफाई को नियंत्रित करना चाहते हैं, जबकि क्लाइंट कोड को बीच में संसाधन को "उधार" लेने की अनुमति देते हैं।
यह एक प्रतिनिधि प्रकार की घोषणा करता है।
public delegate void DataReaderUser( System.Data.IDataReader dataReader );
इस हस्ताक्षर से मेल खाने वाली किसी भी विधि का उपयोग इस प्रकार के प्रतिनिधि को तत्काल करने के लिए किया जा सकता है। C # 2.0 में, यह निहित रूप से किया जा सकता है, बस विधि के नाम का उपयोग करके, साथ ही अनाम विधियों का उपयोग करके।
यह विधि पैरामीटर के रूप में प्रकार का उपयोग करती है। प्रतिनिधि के आह्वान पर ध्यान दें।
public class DataProvider
{
protected string _connectionString;
public DataProvider( string psConnectionString )
{
_connectionString = psConnectionString;
}
public void UseReader( string psSELECT, DataReaderUser readerUser )
{
using ( SqlConnection connection = new SqlConnection( _connectionString ) )
try
{
SqlCommand command = new SqlCommand( psSELECT, connection );
connection.Open();
SqlDataReader reader = command.ExecuteReader();
while ( reader.Read() )
readerUser( reader ); // the delegate is invoked
}
catch ( System.Exception ex )
{
// handle exception
throw ex;
}
}
}
फ़ंक्शन को एक अनाम विधि के साथ निम्नानुसार बुलाया जा सकता है। ध्यान दें कि अनाम विधि स्वयं के बाहर घोषित चर का उपयोग कर सकती है। यह बेहद आसान है (हालांकि उदाहरण थोड़ा विवादित है)।
string sTableName = "test";
string sQuery = "SELECT COLUMN_NAME FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_NAME='" + sTableName + "'";
DataProvider.UseReader( sQuery,
delegate( System.Data.IDataReader reader )
{
Console.WriteLine( sTableName + "." + reader[0] );
} );
प्रतिनिधि अक्सर एक विधि के साथ एक इंटरफ़ेस के स्थान पर उपयोग किया जा सकता है, इसका एक सामान्य उदाहरण पर्यवेक्षक पैटर्न होगा। अन्य भाषाओं में यदि आप एक सूचना प्राप्त करना चाहते हैं कि कुछ हुआ है तो आप कुछ इस तरह परिभाषित कर सकते हैं:
class IObserver{ void Notify(...); }
C # में यह आमतौर पर घटनाओं का उपयोग करके व्यक्त किया जाता है, जहां हैंडलर एक प्रतिनिधि है, उदाहरण के लिए:
myObject.SomeEvent += delegate{ Console.WriteLine("..."); };
प्रतिनिधियों का उपयोग करने के लिए एक और बढ़िया जगह है जब आपको किसी फ़ंक्शन में एक विधेय को पास करना होता है, उदाहरण के लिए जब किसी सूची में आइटम का एक सेट चुनते हैं:
myList.Where(i => i > 10);
उपरोक्त लंबोदर सिंटैक्स का एक उदाहरण है, जिसे निम्नानुसार भी लिखा जा सकता है:
myList.Where(delegate(int i){ return i > 10; });
एक और स्थान जहां प्रतिनिधियों का उपयोग करना उपयोगी हो सकता है, उदाहरण के लिए, कारखाने के कार्यों को पंजीकृत करना है:
myFactory.RegisterFactory(Widgets.Foo, () => new FooWidget());
var widget = myFactory.BuildWidget(Widgets.Foo);
आशा है कि ये आपकी मदद करेगा!
मैं वास्तव में देर से इस पर आ रहा हूं, लेकिन मुझे आज प्रतिनिधियों के उद्देश्य का पता लगाने में परेशानी हो रही थी और दो सरल प्रोग्राम लिखे, जो एक ही आउटपुट देते हैं जो मुझे लगता है कि उनके उद्देश्य को अच्छी तरह से समझाता है।
NoDelegates.cs
using System;
public class Test {
public const int MAX_VALUE = 255;
public const int MIN_VALUE = 10;
public static void checkInt(int a) {
Console.Write("checkInt result of {0}: ", a);
if (a < MAX_VALUE && a > MIN_VALUE)
Console.WriteLine("max and min value is valid");
else
Console.WriteLine("max and min value is not valid");
}
public static void checkMax(int a) {
Console.Write("checkMax result of {0}: ", a);
if (a < MAX_VALUE)
Console.WriteLine("max value is valid");
else
Console.WriteLine("max value is not valid");
}
public static void checkMin(int a) {
Console.Write("checkMin result of {0}: ", a);
if (a > MIN_VALUE)
Console.WriteLine("min value is valid");
else
Console.WriteLine("min value is not valid");
Console.WriteLine("");
}
}
public class Driver {
public static void Main(string [] args) {
Test.checkInt(1);
Test.checkMax(1);
Test.checkMin(1);
Test.checkInt(10);
Test.checkMax(10);
Test.checkMin(10);
Test.checkInt(20);
Test.checkMax(20);
Test.checkMin(20);
Test.checkInt(30);
Test.checkMax(30);
Test.checkMin(30);
Test.checkInt(254);
Test.checkMax(254);
Test.checkMin(254);
Test.checkInt(255);
Test.checkMax(255);
Test.checkMin(255);
Test.checkInt(256);
Test.checkMax(256);
Test.checkMin(256);
}
}
Delegates.cs
using System;
public delegate void Valid(int a);
public class Test {
public const int MAX_VALUE = 255;
public const int MIN_VALUE = 10;
public static void checkInt(int a) {
Console.Write("checkInt result of {0}: ", a);
if (a < MAX_VALUE && a > MIN_VALUE)
Console.WriteLine("max and min value is valid");
else
Console.WriteLine("max and min value is not valid");
}
public static void checkMax(int a) {
Console.Write("checkMax result of {0}: ", a);
if (a < MAX_VALUE)
Console.WriteLine("max value is valid");
else
Console.WriteLine("max value is not valid");
}
public static void checkMin(int a) {
Console.Write("checkMin result of {0}: ", a);
if (a > MIN_VALUE)
Console.WriteLine("min value is valid");
else
Console.WriteLine("min value is not valid");
Console.WriteLine("");
}
}
public class Driver {
public static void Main(string [] args) {
Valid v1 = new Valid(Test.checkInt);
v1 += new Valid(Test.checkMax);
v1 += new Valid(Test.checkMin);
v1(1);
v1(10);
v1(20);
v1(30);
v1(254);
v1(255);
v1(256);
}
}
प्रतिबिंब को गति देने के लिए थोड़ा अलग उपयोग है; हर बार प्रतिबिंब का उपयोग करने के बजाय, आप Delegate.CreateDelegate
एक विधि (ए MethodInfo
) के लिए एक (टाइप) प्रतिनिधि बनाने के लिए उपयोग कर सकते हैं , और उस प्रतिनिधि को इसके बजाय कॉल कर सकते हैं। यह तब प्रति कॉल बहुत तेज है, क्योंकि चेक पहले ही किए जा चुके हैं।
इसके साथ Expression
, आप मक्खी पर कोड बनाने के लिए भी ऐसा ही कर सकते हैं - उदाहरण के लिए, आप आसानी से एक Expression
ऐसा बना सकते हैं जो रनटाइम पर चुने गए प्रकार के लिए + ऑपरेटर का प्रतिनिधित्व करता है (जेनरिक के लिए ऑपरेटर समर्थन प्रदान करने के लिए, जो भाषा प्रदान नहीं करता है) ; और आप Expression
एक टाइप किए गए प्रतिनिधि को काम संकलित कर सकते हैं - काम किया।
प्रतिनिधि किसी भी समय आप घटनाओं का उपयोग करते हैं - यह वह तंत्र है जिसके द्वारा वे काम करते हैं।
इसके अलावा, LINQ क्वेरी का उपयोग करने जैसी चीजों के लिए प्रतिनिधि बहुत उपयोगी होते हैं। उदाहरण के लिए, कई LINQ क्वेरीज़ एक प्रतिनिधि (अक्सर Func<T,TResult>
) लेती हैं जिसका उपयोग फ़िल्टरिंग के लिए किया जा सकता है।
एक उदाहरण यहाँ देखा जा सकता है । आपके पास एक वस्तु को संसाधित करने की एक विधि है जो कुछ आवश्यकताओं को पूरा करती है। हालाँकि, आप ऑब्जेक्ट को कई तरीकों से संसाधित करने में सक्षम होना चाहते हैं। अलग-अलग विधियाँ बनाने के बजाय, आप बस एक मिलान विधि प्रदान कर सकते हैं जो किसी प्रतिनिधि के लिए ऑब्जेक्ट को संसाधित करता है और प्रतिनिधि को उस विधि से पास करता है जो ऑब्जेक्ट का चयन करता है। इस तरह, आप एक चयनकर्ता विधि के लिए विभिन्न तरीकों को असाइन कर सकते हैं। मैंने इसे आसानी से समझने की कोशिश की।
मैं थ्रेड्स के साथ संवाद करने के लिए प्रतिनिधियों का उपयोग करता हूं।
उदाहरण के लिए, मेरे पास एक जीत फ़ॉर्म ऐप हो सकता है जो एक फ़ाइल डाउनलोड करता है। एप्लिकेशन डाउनलोड करने के लिए एक श्रमिक सूत्र शुरू करता है (जो GUI को लॉक होने से रोकता है)। वर्कर थ्रेड प्रतिनिधियों को मुख्य कार्यक्रम में वापस भेजने के लिए स्थिति संदेश (जैसे डाउनलोड प्रगति) का उपयोग करता है, ताकि GUI स्टेटस बार को अपडेट कर सके।
इवेंट हैंडलर के लिए
एक विधि मापदंडों में विधि पारित करने के लिए
ईवेंट, अन्य कोई भी ऑपरेशन
किसी भी समय आप व्यवहार को संक्षिप्त करना चाहते हैं, लेकिन इसे एक समान तरीके से लागू करें। ईवेंट हैंडलर, कॉल-बैक फ़ंक्शंस आदि। आप इंटरफेस और कास्ट्स का उपयोग करके समान चीजों को पूरा कर सकते हैं, लेकिन कभी-कभी, व्यवहार आवश्यक रूप से एक प्रकार या वस्तु से बंधा नहीं होता है। । कभी-कभी आपके पास केवल व्यवहार होता है जिसे आपको एनकैप्सुलेट करने की आवश्यकता होती है।
आलसी पैरामीटर आरंभीकरण! पिछले सभी उत्तरों (रणनीति पैटर्न, पर्यवेक्षक पैटर्न, आदि) के अलावा, प्रतिनिधि आपको मापदंडों के आलसी प्रारंभिककरण को संभालने की अनुमति देते हैं। उदाहरण के लिए, मान लें कि आपके पास एक फ़ंक्शन डाउनलोड () है जिसमें बहुत अधिक समय लगता है और एक निश्चित DownloadedObject देता है। यह ऑब्जेक्ट एक निश्चित शर्तों के आधार पर स्टोरेज द्वारा खपत होता है। आमतौर पर, आप:
storage.Store(conditions, Download(item))
हालाँकि, प्रतिनिधियों के साथ (अधिक सटीक रूप से, लैम्ब्डा) आप स्टोर के हस्ताक्षर को बदलकर निम्नलिखित कर सकते हैं ताकि यह एक शर्त और एक फंक <आइटम, DownloadedObject> प्राप्त करे और इसे इस तरह उपयोग करें:
storage.Store(conditions, (item) => Download(item))
इसलिए, भंडारण केवल प्रतिनिधि का मूल्यांकन करेगा यदि आवश्यक हो, शर्तों के आधार पर डाउनलोड निष्पादित करना।
प्रतिनिधियों का उपयोग
तुलना सरणी में इन ऐरे.सोर्ट (टी [] सरणी, तुलना तुलना), सूची.शॉर्ट (तुलना तुलना), आदि
जहाँ तक मुझे पता है, प्रतिनिधियों को फंक्शन पॉइंटर्स में बदला जा सकता है। यह मूल कोड के साथ कार्य करते समय जीवन को आसान बनाता है, जो कि फ़ंक्शन पॉइंटर्स को लेता है, क्योंकि वे प्रभावी रूप से ऑब्जेक्ट-ओरिएंटेड हो सकते हैं, भले ही मूल प्रोग्रामर ने ऐसा करने के लिए कोई प्रावधान नहीं किया था।
प्रतिनिधि द्वारा किसी विधि को कॉल करने के लिए इसका उपयोग किया जाता है। उदाहरण के लिए:
delegate void del_(int no1,int no2);
class Math
{
public static void add(int x,int y)
{
Console.WriteLine(x+y);
}
public static void sub(int x,int y)
{
Console.WriteLine(x-y);
}
}
class Program
{
static void Main(string[] args)
{
del_ d1 = new del_(Math.add);
d1(10, 20);
del_ d2 = new del_(Math.sub);
d2(20, 10);
Console.ReadKey();
}
}