C # 4.0 ने एक नया प्रकार पेश किया जिसे 'डायनामिक' कहा जाता है। यह सब अच्छा लगता है, लेकिन एक प्रोग्रामर इसका क्या उपयोग करेगा?
क्या ऐसी स्थिति है जहां यह दिन बचा सकता है?
C # 4.0 ने एक नया प्रकार पेश किया जिसे 'डायनामिक' कहा जाता है। यह सब अच्छा लगता है, लेकिन एक प्रोग्रामर इसका क्या उपयोग करेगा?
क्या ऐसी स्थिति है जहां यह दिन बचा सकता है?
जवाबों:
गतिशील कीवर्ड C # 4.0 के लिए नया है, और इसका उपयोग कंपाइलर को बताने के लिए किया जाता है कि एक चर का प्रकार बदल सकता है या यह कि रनटाइम तक ज्ञात नहीं है। इसे किसी कास्ट के बिना इंटरेक्ट करने में सक्षम समझें।
dynamic cust = GetCustomer();
cust.FirstName = "foo"; // works as expected
cust.Process(); // works as expected
cust.MissingMethod(); // No method found!
ध्यान दें कि हमें ग्राहक के रूप में कास्ट करने और न ही कस्टडी घोषित करने की आवश्यकता थी। क्योंकि हमने इसे गतिशील घोषित किया था, रनटाइम खत्म हो गया और फिर हमारे लिए FirstName संपत्ति खोजता है और सेट करता है। अब, निश्चित रूप से, जब आप एक गतिशील चर का उपयोग कर रहे हैं, तो आप संकलक प्रकार की जाँच छोड़ रहे हैं। इसका अर्थ है कॉल कस्ट.मिसिंगमेथोड () संकलन और रनटाइम तक विफल नहीं होगा। इस ऑपरेशन का परिणाम एक RuntimeBinderException है क्योंकि MissingMethod ग्राहक वर्ग पर परिभाषित नहीं है।
ऊपर दिए गए उदाहरण से पता चलता है कि विधियों और गुणों को कॉल करते समय गतिशील कैसे काम करता है। एक अन्य शक्तिशाली (और संभावित खतरनाक) सुविधा विभिन्न प्रकार के डेटा के लिए चर का पुन: उपयोग करने में सक्षम हो रही है। मुझे यकीन है कि पायथन, रूबी और पर्ल प्रोग्रामर इसका फायदा उठाने के लिए एक लाख तरीके सोच सकते हैं, लेकिन मैं सी # का उपयोग इतने लंबे समय से कर रहा हूं कि यह मेरे लिए "गलत" लगता है।
dynamic foo = 123;
foo = "bar";
ठीक है, इसलिए आपको सबसे अधिक संभावना उपरोक्त की तरह कोड लिखना नहीं होगा। हालांकि, ऐसे समय हो सकते हैं, जब चर पुन: उपयोग में आ सकता है या विरासत कोड के एक गंदे टुकड़े को साफ कर सकता है। एक साधारण मामला जो मैं अक्सर चलाता हूं, वह लगातार दशमलव और दोहरे के बीच डालना होता है।
decimal foo = GetDecimalValue();
foo = foo / 2.5; // Does not compile
foo = Math.Sqrt(foo); // Does not compile
string bar = foo.ToString("c");
दूसरी लाइन संकलित नहीं करती है क्योंकि 2.5 को डबल के रूप में टाइप किया जाता है और लाइन 3 को संकलित नहीं किया जाता है क्योंकि Math.Sqrt एक डबल की अपेक्षा करता है। जाहिर है, आपको बस इतना करना है और अपने वैरिएबल टाइप को कास्ट और / या बदलना है, लेकिन ऐसी परिस्थितियां भी हो सकती हैं, जहां डायनामिक उपयोग करने के लिए समझ में आता है।
dynamic foo = GetDecimalValue(); // still returns a decimal
foo = foo / 2.5; // The runtime takes care of this for us
foo = Math.Sqrt(foo); // Again, the DLR works its magic
string bar = foo.ToString("c");
और अधिक पढ़ें सुविधा: http://www.codeproject.com/KB/cs/CSharp4Features.aspx
dynamic
c # सुविधाओं के समाधान के लिए c # के उपयोग के बारे में सोचता हूं जो मानक c # सुविधाओं और स्थिर टाइपिंग द्वारा हल किया जा सकता है (शायद इससे भी बेहतर) या टाइप इंट्रेंस के साथ ( var
)। इसका उपयोग केवल तब किया dynamic
जाना चाहिए जब यह DLR के साथ इंटरऑपरेबिलिटी मुद्दों पर आता है। यदि आप एक स्थिर टाइप की गई भाषा में कोड लिखते हैं, जैसे c # है, तो इसे करें, और न ही डायनेमिक भाषा का अनुकरण करें। बस बदसूरत है।
dynamic
अपने कोड में चर का भारी उपयोग करते हैं, जहां आपको उनकी आवश्यकता नहीं है (जैसे कि आपके उदाहरण में स्क्वररूट) तो आप क्लीन कंपाइल टाइम एरर चेकिंग छोड़ देते हैं; इसके बजाय अब आप संभावित रनटाइम त्रुटियाँ प्राप्त कर रहे हैं।
dynamic
कीवर्ड भी जुड़ गया, एक साथ सी # 4.0 के कई अन्य नई सुविधाओं के साथ, यह सरल कोड से बात करने के बनाने के लिए है कि में जीवन या अन्य runtimes, अलग एपीआई है से आता है।
एक उदाहरण लीजिए।
यदि आपके पास एक COM ऑब्जेक्ट है, जैसे Word.Application
ऑब्जेक्ट, और एक दस्तावेज़ खोलना चाहते हैं, तो ऐसा करने की विधि 15 से कम मापदंडों के साथ नहीं आती है, जिनमें से अधिकांश वैकल्पिक हैं।
इस पद्धति को कॉल करने के लिए, आपको कुछ इस तरह की आवश्यकता होगी (मैं सरल कर रहा हूं, यह वास्तविक कोड नहीं है):
object missing = System.Reflection.Missing.Value;
object fileName = "C:\\test.docx";
object readOnly = true;
wordApplication.Documents.Open(ref fileName, ref missing, ref readOnly,
ref missing, ref missing, ref missing, ref missing, ref missing,
ref missing, ref missing, ref missing, ref missing, ref missing,
ref missing, ref missing);
उन सभी तर्कों पर ध्यान दें? आपको संस्करण 4.0 से पहले C # के बाद से पास करने की आवश्यकता है, जिसमें वैकल्पिक तर्कों की धारणा नहीं है। C # 4.0 में, COM API को शुरू करने के साथ काम करना आसान बना दिया गया है:
ref
COM API के लिए वैकल्पिक बनानाउपरोक्त कॉल के लिए नया सिंटैक्स होगा:
wordApplication.Documents.Open(@"C:\Test.docx", ReadOnly: true);
देखें कि यह कितना आसान लगता है, यह कितना अधिक पठनीय बन जाता है?
चलो इसे तोड़ दो:
named argument, can skip the rest
|
v
wordApplication.Documents.Open(@"C:\Test.docx", ReadOnly: true);
^ ^
| |
notice no ref keyword, can pass
actual parameter values instead
जादू यह है कि सी # संकलक अब आवश्यक कोड को इंजेक्ट करेगा, और रनटाइम में नई कक्षाओं के साथ काम करेगा, लगभग वही काम करने के लिए जो आपने पहले किया था, लेकिन सिंटैक्स आपसे छिपा हुआ है, अब आप इस पर ध्यान केंद्रित कर सकते हैं क्या , और कैसे पर इतना नहीं । एंडर्स हेजेलबर्ग यह कहने के शौकीन हैं कि आपको अलग-अलग "भस्म" का आह्वान करना होगा, जो कि पूरी चीज़ के जादू पर एक प्रकार का दंड है, जहां आपको आमतौर पर अपना हाथ लहराना होता है और सही क्रम में कुछ जादू शब्द बोलना होता है। एक निश्चित प्रकार की वर्तनी प्राप्त करने के लिए। COM ऑब्जेक्ट्स से बात करने का पुराना एपीआई तरीका बहुत कुछ था, आपको कोड को संकलित करने के लिए संकलक को सहलाने के लिए बहुत सारे हुप्स के माध्यम से कूदने की आवश्यकता थी।
संस्करण 4.0 से पहले सी # में चीजें टूट जाती हैं यदि आप किसी COM ऑब्जेक्ट से बात करने की कोशिश करते हैं, जिसके लिए आपके पास कोई इंटरफ़ेस या क्लास नहीं है, तो आपके पास एक IDispatch
संदर्भ है।
यदि आप नहीं जानते कि यह क्या है, IDispatch
तो मूल रूप से COM वस्तुओं के लिए प्रतिबिंब है। एक IDispatch
इंटरफ़ेस के साथ आप ऑब्जेक्ट से पूछ सकते हैं "सहेजें के रूप में ज्ञात विधि के लिए आईडी नंबर क्या है", और तर्क मान वाले एक निश्चित प्रकार के सरणियों का निर्माण करें, और अंत में Invoke
विधि IDispatch
को कॉल करने के लिए इंटरफ़ेस पर एक विधि को कॉल करें, सभी पासिंग वह सूचना जिसे आपने एक साथ करने में कामयाब रहे हैं।
उपरोक्त सहेजें विधि इस तरह दिख सकती है (यह निश्चित रूप से सही कोड नहीं है):
string[] methodNames = new[] { "Open" };
Guid IID = ...
int methodId = wordApplication.GetIDsOfNames(IID, methodNames, methodNames.Length, lcid, dispid);
SafeArray args = new SafeArray(new[] { fileName, missing, missing, .... });
wordApplication.Invoke(methodId, ... args, ...);
यह सब सिर्फ एक दस्तावेज खोलने के लिए।
VB के पास लंबे समय पहले इस बॉक्स के अधिकांश के लिए वैकल्पिक तर्क और समर्थन थे, इसलिए यह C # कोड:
wordApplication.Documents.Open(@"C:\Test.docx", ReadOnly: true);
मूल रूप से अभिव्यक्ति के संदर्भ में VB को केवल C # पकड़ रहा है, लेकिन इसे सही तरीके से कर रहा है, इसे विस्तार योग्य बनाकर, और सिर्फ COM के लिए नहीं। बेशक यह VB.NET या .NET रनटाइम के शीर्ष पर निर्मित किसी अन्य भाषा के लिए भी उपलब्ध है।
आप IDispatch
इंटरफ़ेस के बारे में अधिक जानकारी विकिपीडिया: IDispatch पर प्राप्त कर सकते हैं यदि आप इसके बारे में अधिक पढ़ना चाहते हैं। यह वास्तव में सामान है।
हालांकि, क्या होगा अगर आप एक पायथन ऑब्जेक्ट से बात करना चाहते हैं? COM ऑब्जेक्ट्स के लिए उपयोग किए जाने वाले एक से अधिक के लिए एक अलग API है, और चूंकि पायथन ऑब्जेक्ट प्रकृति में गतिशील हैं, इसलिए आपको कॉल करने के लिए सही तरीके, उनके मापदंडों आदि को खोजने के लिए जादू का सहारा लेने की आवश्यकता है, लेकिन .NET नहीं। प्रतिबिंब, पायथन के लिए कुछ लिखा गया है, ऊपर दिए गए IDispatch कोड की तरह ही, बिल्कुल अलग।
और रूबी के लिए? एक अलग एपीआई अभी भी।
जावास्क्रिप्ट? समान सौदा, उसके लिए भी अलग एपीआई।
डायनामिक कीवर्ड में दो चीज़ें होती हैं:
dynamic
dynamic
कीवर्ड की आवश्यकता होती है, और कॉल को चीजों को करने के सही तरीके से मैप करता है। एपीआई को भी प्रलेखित किया गया है, इसलिए यदि आपके पास ऐसी वस्तुएं हैं जो एक रनटाइम से आती हैं, तो आप इसे जोड़ नहीं सकते हैं।dynamic
कीवर्ड नहीं है, तथापि, किसी भी मौजूदा नेट-केवल कोड की जगह के लिए है। निश्चित रूप से, आप इसे कर सकते हैं, लेकिन इसे इस कारण से नहीं जोड़ा गया था, और फ्रंट में एंडर्स हेजलबर्ग के साथ सी # प्रोग्रामिंग भाषा के लेखक, सबसे अधिक अडिग रहे हैं कि वे अभी भी सी # को एक जोरदार टाइप की हुई भाषा मानते हैं, और बलिदान नहीं करेंगे वह सिद्धांत।
इसका मतलब है कि यद्यपि आप इस तरह कोड लिख सकते हैं:
dynamic x = 10;
dynamic y = 3.14;
dynamic z = "test";
dynamic k = true;
dynamic l = x + y * z - k;
और यह संकलित है, यह जादू-चलो-आंकड़ा-आउट-क्या-आप-मतलब-पर-रनटाइम प्रकार की प्रणाली के रूप में नहीं था।
संपूर्ण उद्देश्य अन्य प्रकार की वस्तुओं से बात करना आसान बनाना था।
इंटरनेट पर कीवर्ड, प्रस्तावकों, विरोधियों, चर्चा, शेख़ी, प्रशंसा, आदि के बारे में बहुत सारी सामग्री है।
मेरा सुझाव है कि आप निम्न लिंक से शुरू करते हैं और फिर अधिक के लिए Google:
dynamic
जोड़ा गया था कि कैसे परावर्तन जैसी विधि के लिए अन्य पारिस्थितिक तंत्रों का समर्थन किया जा सकता है, साथ ही इसे प्राप्त करने के दस्तावेज तरीके के साथ डेटा संरचनाओं को एक प्रकार का ब्लैक बॉक्स दृष्टिकोण प्रदान किया जाता है।
मुझे आश्चर्य है कि किसी ने कई प्रेषण का उल्लेख नहीं किया । इसके चारों ओर काम करने का सामान्य तरीका विज़िटर पैटर्न के माध्यम से है और यह हमेशा संभव नहीं होता है इसलिए आप स्टैक्ड हो जाते हैंis
चेक के ।
तो यहाँ मेरे खुद के आवेदन का एक वास्तविक जीवन उदाहरण है। करने के बजाय:
public static MapDtoBase CreateDto(ChartItem item)
{
if (item is ElevationPoint) return CreateDtoImpl((ElevationPoint)item);
if (item is MapPoint) return CreateDtoImpl((MapPoint)item);
if (item is MapPolyline) return CreateDtoImpl((MapPolyline)item);
//other subtypes follow
throw new ObjectNotFoundException("Counld not find suitable DTO for " + item.GetType());
}
तुम करो:
public static MapDtoBase CreateDto(ChartItem item)
{
return CreateDtoImpl(item as dynamic);
}
private static MapDtoBase CreateDtoImpl(ChartItem item)
{
throw new ObjectNotFoundException("Counld not find suitable DTO for " + item.GetType());
}
private static MapDtoBase CreateDtoImpl(MapPoint item)
{
return new MapPointDto(item);
}
private static MapDtoBase CreateDtoImpl(ElevationPoint item)
{
return new ElevationDto(item);
}
ध्यान दें कि पहले मामले ElevationPoint
में उप-वर्ग है MapPoint
और अगर इसे पहले नहीं रखा गया है तो यह MapPoint
कभी भी नहीं पहुंचेगा। यह गतिशील के साथ ऐसा नहीं है, क्योंकि निकटतम मिलान विधि को बुलाया जाएगा।
जैसा कि आप कोड से अनुमान लगा सकते हैं, यह विशेषता तब काम आई जब मैं चार्ट इटेम ऑब्जेक्ट्स से उनके क्रमबद्ध संस्करणों में अनुवाद कर रहा था। मैं आगंतुकों के साथ अपने कोड को प्रदूषित नहीं करना चाहता था और मैं यह भी नहीं चाहता था कि मैं ChartItem
बेकार वस्तुओं को विशिष्ट विशेषताओं के साथ प्रदूषित कर दूं ।
is
एक के ऊपर एक खूंखार स्टैक्ड के साथ साइक्लोमैटिक जटिलता बढ़ गई ।
magic
; जादू जैसी कोई चीज नहीं है।
डीएलआर (गतिशील भाषा रनटाइम) पर चलने वाले, गतिशील लोगों (अजगर, रूबी ...) के साथ संभोग करने के लिए स्थिर टाइप की गई भाषाओं (सीएलआर) के लिए यह आसान बनाता है : MSDN देखें :
उदाहरण के लिए, आप XML में C # में काउंटर बढ़ाने के लिए निम्न कोड का उपयोग कर सकते हैं।
Scriptobj.SetProperty("Count", ((int)GetProperty("Count")) + 1);
DLR का उपयोग करके, आप एक ही ऑपरेशन के लिए निम्नलिखित कोड का उपयोग कर सकते हैं।
scriptobj.Count += 1;
MSDN इन लाभों को सूचीबद्ध करता है:
- .NET फ्रेमवर्क में डायनामिक लैंग्वेज को पोर्ट करना सरल करता है
- स्टैटिकली टाइप की गई भाषाओं में डायनामिक फीचर्स सक्षम करता है
- DLR और .NET फ्रेमवर्क के भविष्य के लाभ प्रदान करता है
- लाइब्रेरीज़ और ऑब्जेक्ट्स को साझा करना सक्षम करता है
- फास्ट डायनेमिक डिस्पैच और इनवोकेशन प्रदान करता है
अधिक विवरण के लिए MSDN देखें ।
उपयोग का एक उदाहरण:
आप कई वर्गों का उपभोग करते हैं जिनके पास एक सांप्रदायिक संपत्ति है 'क्रिएशनडेट':
public class Contact
{
// some properties
public DateTime CreationDate { get; set; }
}
public class Company
{
// some properties
public DateTime CreationDate { get; set; }
}
public class Opportunity
{
// some properties
public DateTime CreationDate { get; set; }
}
यदि आप एक सांप्रदायिक विधि लिखते हैं, जो 'क्रिएशनडेट' संपत्ति का मान प्राप्त करता है, तो आपको प्रतिबिंब का उपयोग करना होगा:
static DateTime RetrieveValueOfCreationDate(Object item)
{
return (DateTime)item.GetType().GetProperty("CreationDate").GetValue(item);
}
'गतिशील' अवधारणा के साथ, आपका कोड बहुत अधिक सुरुचिपूर्ण है:
static DateTime RetrieveValueOfCreationDate(dynamic item)
{
return item.CreationDate;
}
COM इंटरॉप। खासतौर पर IUnogn। इसे खासतौर पर इसके लिए डिजाइन किया गया था।
इसका उपयोग कोड गुणवत्ता, इंटेलीजेंसी को नष्ट करने और टाइम बग डिटेक्शन को संकलित करने के लिए ज्यादातर राड और पायथन पीड़ितों द्वारा किया जाएगा ।
यह रनटाइम पर मूल्यांकन करता है, जिससे आप जावास्क्रिप्ट में अपने इच्छित प्रकार को स्विच कर सकते हैं। यह कानूनी है:
dynamic i = 12;
i = "text";
और इसलिए आप आवश्यकता के अनुसार प्रकार बदल सकते हैं। इसे अंतिम उपाय के रूप में उपयोग करें; यह फायदेमंद है, लेकिन मैंने सुना है कि उत्पन्न आईएल के संदर्भ में दृश्यों के तहत बहुत कुछ होता है और यह एक प्रदर्शन मूल्य पर आ सकता है।
मेरे लिए 'डायनेमिक' प्रकार के चर का सबसे अच्छा उपयोग तब हुआ था, जब हाल ही में, मैं ADO.NET ( SQLDataReader का उपयोग करके ) में एक डेटा एक्सेस लेयर लिख रहा था और कोड पहले से ही लिखित विरासत संग्रहित प्रक्रियाओं को लागू कर रहा था। व्यापार तर्क के थोक युक्त उन विरासत संग्रहित प्रक्रियाओं के सैकड़ों हैं। मेरे डेटा एक्सेस लेयर को कुछ हेरफेर करने के लिए, बिजनेस लॉजिक लेयर, C # आधारित, को कुछ प्रकार के संरचित डेटा को वापस करने की आवश्यकता होती है ( हालांकि लगभग कोई भी नहीं हैं )। प्रत्येक संग्रहीत कार्यविधियाँ डेटा के अलग सेट ( टेबल कॉलम ) लौटाती हैं । इसलिए लौटे हुए डेटा को रखने और उसे BLL में पास करने के लिए दर्जनों कक्षाएं या स्ट्रक्चर्स बनाने के बजाय, मैंने नीचे दिया गया कोड लिखा, जो काफी सुरुचिपूर्ण और साफ-सुथरा दिखता है।
public static dynamic GetSomeData(ParameterDTO dto)
{
dynamic result = null;
string SPName = "a_legacy_stored_procedure";
using (SqlConnection connection = new SqlConnection(DataConnection.ConnectionString))
{
SqlCommand command = new SqlCommand(SPName, connection);
command.CommandType = System.Data.CommandType.StoredProcedure;
command.Parameters.Add(new SqlParameter("@empid", dto.EmpID));
command.Parameters.Add(new SqlParameter("@deptid", dto.DeptID));
connection.Open();
using (SqlDataReader reader = command.ExecuteReader())
{
while (reader.Read())
{
dynamic row = new ExpandoObject();
row.EmpName = reader["EmpFullName"].ToString();
row.DeptName = reader["DeptName"].ToString();
row.AnotherColumn = reader["AnotherColumn"].ToString();
result = row;
}
}
}
return result;
}
dynamic np = Py.Import("numpy")
dynamic
पर संख्यात्मक ऑपरेटरों को लागू करते समय जेनरिक कास्ट कर सकते हैं। यह प्रकार की सुरक्षा प्रदान करता है और जेनरिक की सीमाओं से बचता है। यह सार में है * बतख टाइपिंग:T y = x * (dynamic)x
, कहाँ पे typeof(x) is T
dynamic
टाइपिंग के लिए एक और उपयोग का मामला आभासी तरीकों के लिए है जो कोवरियन या कंट्रोवर्सी के साथ समस्या का अनुभव करते हैं। ऐसा ही एक उदाहरण कुख्यात Clone
तरीका है जो उसी प्रकार की वस्तु को लौटाता है जिस तरह की वस्तु को कहा जाता है। यह समस्या पूरी तरह से एक गतिशील रिटर्न के साथ हल नहीं होती है क्योंकि यह स्थैतिक प्रकार की जाँच को दरकिनार कर देती है, लेकिन कम से कम आपको सादे का उपयोग करते समय हर समय बदसूरत कलाकारों का उपयोग करने की आवश्यकता नहीं होती है object
। अन्यथा कहने के लिए, जातियां अंतर्निहित हो जाती हैं।
public class A
{
// attributes and constructor here
public virtual dynamic Clone()
{
var clone = new A();
// Do more cloning stuff here
return clone;
}
}
public class B : A
{
// more attributes and constructor here
public override dynamic Clone()
{
var clone = new B();
// Do more cloning stuff here
return clone;
}
}
public class Program
{
public static void Main()
{
A a = new A().Clone(); // No cast needed here
B b = new B().Clone(); // and here
// do more stuff with a and b
}
}