2008-08-28 17 views
279

किसी को भी मुझे बता सकते हैं अगर वहाँ केवल करने के लिए एक सामान्य प्रकार तर्क T सीमित करने के लिए जेनरिक के साथ एक तरीका है:क्या कोई बाधा है जो मेरी जेनेरिक विधि को संख्यात्मक प्रकारों पर प्रतिबंधित करती है?

  • Int16
  • Int32
  • Int64
  • UInt16
  • UInt32
  • UInt64

मैं where कीवर्ड के बारे में पता कर रहा हूँ, लेकिन केवल इन प्रकार के लिए एक इंटरफेस नहीं मिल रहा है,

कुछ की तरह:

static bool IntegerFunction<T>(T value) where T : INumeric 

उत्तर

113

Hejlsberg ब्रूस एकेल साथ सुविधा in an interview को लागू न करने के कारणों का वर्णन किया है।

मुझे स्वीकार करना है, हालांकि, मुझे नहीं पता कि वह कैसे सोचता है कि उसका प्रस्तावित कामकाज काम करेगा। उनका प्रस्ताव कुछ अन्य सामान्य वर्ग (साक्षात्कार पढ़ें!) में अंकगणितीय परिचालन को स्थगित करना है। यह कैसे मदद करता है? आईएमएचओ, ज्यादा नहीं।

+22

बीटीडब्ल्यू, MiscUtil एक सामान्य वर्ग प्रदान करता है जो वास्तव में करता है; 'ऑपरेटर'/'ऑपरेटर '; http://www.yoda.arachsys.com/csharp/miscutil/usage/genericoperators.html –

+1

@ मार्क: अच्छी टिप्पणी। हालांकि, बस स्पष्ट होने के लिए, मुझे नहीं लगता कि हेजल्सबर्ग समस्या के समाधान के रूप में कोड पीढ़ी का जिक्र कर रहा था जैसा कि आप 'ऑपरेटर ' कोड में करते हैं (क्योंकि साक्षात्कार 'अभिव्यक्तियों' के अस्तित्व से बहुत पहले दिया गया था फ्रेमवर्क, भले ही कोई निश्चित रूप से 'प्रतिबिंब। प्रवेश' का उपयोग कर सके) - और मैं वास्तव में * उसके * कामकाज में दिलचस्पी लेता हूं। –

+0

@ कोनराड रुडॉल्फ: मुझे लगता है [यह जवाब] (http://stackoverflow.com/questions/1348594/is-there-ac-generic-constraint-for-real-number-types/1348625#1348625) एक समान प्रश्न के लिए हेजल्सबर्ग के कामकाज बताते हैं। अन्य सामान्य वर्ग अमूर्त बना दिया गया है। चूंकि आपको प्रत्येक प्रकार के लिए अन्य जेनेरिक क्लास को कार्यान्वित करने की आवश्यकता है, जिसके परिणामस्वरूप आप समर्थन करना चाहते हैं, इसके परिणामस्वरूप डुप्लिकेट कोड होगा, लेकिन इसका मतलब यह है कि आप मूल जेनेरिक क्लास को केवल समर्थित प्रकार के साथ तुरंत चालू कर सकते हैं। – Ergwun

-5

कोई एकल इंटरफेस या आधार वर्ग नहीं है कि वे सभी विरासत (जो अन्य वर्गों द्वारा भी विरासत में नहीं है) तो सरल जवाब नहीं है।

मुझे आश्चर्य है कि यह एक मुद्दा क्यों है। आप अपने इंटीजर फ़ंक्शन कक्षा के अंदर क्या करना चाहते हैं जो केवल पूर्णांक के लिए किया जा सकता है?

+2

मुझे आश्चर्य है कि यहां जवाब देने वाले कई लोगों को अवधारणा को समझने में इतनी परेशानी क्यों थी। मेरे मामले में, मैं किसी भी पूर्णांक या enum प्रकार पर,,,, और ~ करना चाहता हूँ। स्काला जैसी अच्छी तरह से डिज़ाइन की गई भाषाएं ऐसे जेनेरिकों को अनुमति देती हैं। (यहां तक ​​कि सी ++ जैसी क्रैपी भाषाएं उन्हें अनुमति देती हैं।) –

+1

कस्टम क्लास बनाने और उस वर्ग पर बाधा बनाने का एक विकल्प होगा, फिर प्रत्येक मूल्य प्रकार के लिए निहित कास्ट ऑपरेटर बनाएं जिन्हें आप समर्थन देना चाहते हैं। आपको अपनी कस्टम बाधा वर्ग पर प्रत्येक और, और ~ ऑपरेटरों को भी लागू करना होगा। – samjudson

72

इसके लिए कोई बाधा नहीं है। संख्यात्मक गणना के लिए जेनेरिक का उपयोग करने के इच्छुक व्यक्ति के लिए यह एक वास्तविक मुद्दा है।

मैं आगे जाकर कहते हैं कि हम

static bool GenericFunction<T>(T value) 
    where T : operators(+, -, /, *) 

या यहां तक ​​कि

static bool GenericFunction<T>(T value) 
    where T : Add, Subtract 

जरूरत दुर्भाग्य से आप केवल इंटरफेस, आधार वर्ग और कीवर्ड struct है (मूल्य-प्रकार होना चाहिए) चाहते हैं, class (संदर्भ प्रकार होना चाहिए) और new() (डिफ़ॉल्ट डिफॉल्ट कन्स्ट्रक्टर होना चाहिए)

आप किसी और चीज़ में संख्या को लपेट सकते हैं (समान INullable<T>) here on codeproject की तरह।


आप कार्यावधि में लेकिन यह है कि पहली जगह में सामान्य होने का लाभ खोना करता है (ऑपरेटरों के लिए दर्शाती या प्रकार के लिए जाँच करके) प्रतिबंध लागू हो सकते हैं।

+2

मुझे आश्चर्य है कि आपने जेनेरिक ऑपरेटरों के लिए MiscUtil का समर्थन देखा है ... http://www.yoda.arachsys.com/csharp/miscutil/usage/genericoperators.html –

+9

हाँ - जॉन स्कीट ने मुझे किसी और चीज़ के लिए इंगित किया जबकि पहले (लेकिन इस साल पुरानी प्रतिक्रिया के बाद) - वे एक चालाक विचार हैं, लेकिन मुझे अभी भी उचित बाधा समर्थन पसंद है। – Keith

+1

रुको, 'जहां टी: ऑपरेटर (+, -, /, *) 'कानूनी सी # है? नौसिखिया प्रश्न के लिए खेद है। – kdbanman

10

शायद निकटतम आप कर सकते हैं

static bool IntegerFunction<T>(T value) where T: struct 

सुनिश्चित नहीं हैं कि यदि आप निम्नलिखित

static bool IntegerFunction<T>(T value) where T: struct, IComparable 
, IFormattable, IConvertible, IComparable<T>, IEquatable<T> 

कुछ तो विशिष्ट, क्यों सिर्फ प्रत्येक प्रकार के लिए भार के लिए नहीं के लिए कर सकता है है, सूची है इतना छोटा और यह संभवतः कम स्मृति पदचिह्न होगा।

2

मैं सैमजसन के समान ही सोच रहा था, केवल पूर्णांक क्यों? और यदि ऐसा है, तो आप एक सहायक वर्ग या ऐसा कुछ भी बनाना चाहते हैं जो आप चाहते हैं कि सभी प्रकार के हो।

यदि आप सभी चाहते हैं कि पूर्णांक हैं, तो सामान्य का उपयोग न करें, जो सामान्य नहीं है; या बेहतर अभी तक, किसी अन्य प्रकार को अपने प्रकार की जांच करके अस्वीकार कर दें।

15

दुर्भाग्य से आप केवल इस उदाहरण में जहां खंड में संरचना निर्दिष्ट करने में सक्षम हैं। यह अजीब लगता है कि आप विशेष रूप से Int16, Int32, आदि निर्दिष्ट नहीं कर सकते हैं, लेकिन मुझे यकीन है कि कुछ गहरा कार्यान्वयन कारण है जहां निर्णय में अंतर्निहित किसी भी खंड में मूल्य प्रकारों की अनुमति नहीं है।

मुझे लगता है कि एकमात्र समाधान एक रनटाइम चेक करना है जो दुर्भाग्य से संकलन समय पर उठाई गई समस्या को रोकता है। यह कुछ ऐसा होगा: -

static bool IntegerFunction<T>(T value) where T : struct { 
    if (typeof(T) != typeof(Int16) && 
     typeof(T) != typeof(Int32) && 
     typeof(T) != typeof(Int64) && 
     typeof(T) != typeof(UInt16) && 
     typeof(T) != typeof(UInt32) && 
     typeof(T) != typeof(UInt64)) { 
    throw new ArgumentException(
     string.Format("Type '{0}' is not valid.", typeof(T).ToString())); 
    } 

    // Rest of code... 
} 

जो मुझे पता है कि थोड़ा सा बदसूरत है, लेकिन कम से कम आवश्यक बाधाओं को प्रदान करता है।

मैं इस कार्यान्वयन के लिए संभावित प्रदर्शन प्रभावों को भी देखता हूं, शायद वहां एक तेज़ तरीका है।

+11

+1 था, हालांकि, '// शेष कोड ...' संकलित नहीं हो सकता है अगर यह बाधाओं द्वारा परिभाषित संचालन पर निर्भर करता है। – Nick

+1

कनवर्ट करें। ToIntXX (मान) "// शेष कोड" संकलित करने में मदद कर सकता है - कम से कम जब तक इंटीजर फ़ंक्शन का रिटर्न प्रकार टाइप टी का भी होता है, तो आप hooped हैं। : -पी – yoyo

+0

-1; यह @ निक द्वारा दिए गए कारण के लिए काम नहीं करता है। जिस क्षण आप '// शेष कोड ... 'जैसे' मूल्य + मान' या' मान * मान' में कोई अंकगणितीय परिचालन करने का प्रयास करते हैं, तो आपको संकलन त्रुटि मिली है। –

-9

मुझे लगता है कि आप जेनेरिक गलतफहमी कर रहे हैं। यदि आप जिस ऑपरेशन को करने का प्रयास कर रहे हैं वह केवल विशिष्ट डेटा प्रकारों के लिए अच्छा है तो आप कुछ "जेनेरिक" नहीं कर रहे हैं।

इसके अलावा, चूंकि आप केवल फ़ंक्शन को इंट डेटा प्रकारों पर काम करने की अनुमति देना चाहते हैं, तो आपको प्रत्येक विशिष्ट आकार के लिए एक अलग फ़ंक्शन की आवश्यकता नहीं होनी चाहिए। बस सबसे बड़े विशिष्ट प्रकार में पैरामीटर लेना प्रोग्राम को छोटे डेटा प्रकारों को स्वचालित रूप से ऊपर उठाने की अनुमति देगा। (यानी एक इंटेल 16 पास करने पर कॉल करने पर इंट 64 में स्वतः कनवर्ट किया जाएगा)।

यदि आप फ़ंक्शन में पारित होने वाले वास्तविक आकार के आधार पर अलग-अलग संचालन कर रहे हैं तो मुझे लगता है कि आपको जो भी कर रहे हैं, उसे करने की कोशिश करने पर भी गंभीरता से पुनर्विचार करना चाहिए। यदि आपको भाषा को बेवकूफ बनाना है तो आपको जो कुछ करना है, उसके बजाय आपको जो कुछ करने की कोशिश कर रहा है उसके बारे में थोड़ा और सोचना चाहिए।

अन्य सभी को विफल करना, ऑब्जेक्ट का एक पैरामीटर इस्तेमाल किया जा सकता है और फिर आपको पैरामीटर के प्रकार की जांच करनी होगी और उचित कार्रवाई करना होगा या अपवाद फेंकना होगा।

+10

कक्षा हिस्टोग्राम पर विचार करें। यह एक सामान्य पैरामीटर लेने के लिए समझ में आता है, इसलिए संकलक इसे बाइट्स, इंट्स, युगल, दशमलव, बिगइन्ट, के लिए अनुकूलित कर सकता है ...लेकिन वही आपको रोकने की जरूरत है कि आप हिस्टोग्राम बना सकते हैं, क्योंकि - ट्रॉन के साथ बोलना - यह गणना नहीं करता है। (शाब्दिक :) :) – sunside

+14

आप वह हैं जो जेनेरिकों को गलत समझते हैं। मेटाप्रोग्रामिंग केवल उन मानों पर काम नहीं कर रहा है जो * किसी भी संभावित प्रकार * हो सकते हैं, यह उन प्रकारों पर चलने के लिए है जो विभिन्न * बाधाओं * फिट बैठते हैं। –

1

व्यायाम का बिंदु क्या है?

जैसा कि लोगों ने पहले ही बताया है, आप एक गैर-जेनेरिक फ़ंक्शन को सबसे बड़ा आइटम ले सकते हैं, और कंपाइलर स्वचालित रूप से आपके लिए छोटे इंट्स को परिवर्तित कर देगा।

static bool IntegerFunction(Int64 value) { } 

अपने कार्य प्रदर्शन के महत्वपूर्ण मार्ग (बहुत संभावना नहीं, IMO) पर है, तो आप सभी आवश्यक कार्यों के लिए भार के प्रदान कर सकता है।

static bool IntegerFunction(Int64 value) { } 
... 
static bool IntegerFunction(Int16 value) { } 
+20

और फिर महत्वपूर्ण कोड डुप्लिकेशन के साथ समाप्त होता है। –

+1

मैं संख्यात्मक तरीकों के साथ बहुत काम करता हूं। कभी-कभी मैं पूर्णांक चाहता हूं और कभी-कभी मुझे फ़्लोटिंग पॉइंट चाहिए। दोनों में 64 बिट संस्करण हैं जो प्रसंस्करण गति के लिए इष्टतम हैं। इनके बीच कनवर्ट करना एक भयानक विचार है क्योंकि हर तरह नुकसान होता है। जबकि मैं युगल का उपयोग करने की ओर रुख करता हूं, कभी-कभी मुझे पूर्णांक का उपयोग करना बेहतर लगता है क्योंकि उन्हें कहीं और कैसे उपयोग किया जाता है। लेकिन यह बहुत अच्छा होगा जब मैं इसे एक बार करने के लिए एक एल्गोरिदम लिख रहा हूं और उदाहरण आवश्यकताओं के लिए प्रकार का निर्णय छोड़ देता हूं। – VoteCoffee

16

यह प्रश्न एक सामान्य प्रश्न है, इसलिए मैं इसे विकी के रूप में पोस्ट कर रहा हूं (क्योंकि मैंने पहले इसी तरह पोस्ट किया है, लेकिन यह एक पुराना है); वैसे भी ...

आप .NET का किस संस्करण का उपयोग कर रहे हैं? यदि आप .NET 3.5 का उपयोग कर रहे हैं, तो मेरे पास MiscUtil (फ्री इत्यादि) में generic operators implementation है।

यह विभिन्न प्रकारों पर अंकगणित के लिए T Add<T>(T x, T y) तरह के तरीकों, और अन्य वेरिएंट (जैसे DateTime + TimeSpan) है।

इसके अतिरिक्त, यह सभी अंतर्निहित, उठाए गए और bespoke ऑपरेटरों के लिए काम करता है, और प्रदर्शन के लिए प्रतिनिधि को कैश करता है।

यह कुछ मुश्किल पृष्ठभूमि क्यों है यह मुश्किल है here

तुम भी पता चला है कि dynamic (4.0) एक तरह से-हल करती है इस मुद्दे को परोक्ष रूप से भी कर सकते हैं - यानी

dynamic x = ..., y = ... 
dynamic result = x + y; // does what you expect 
1

मैं एक सामान्य से एक है जो आप externaly संभाल सकता का प्रयोग करेंगे ...

/// <summary> 
/// Generic object copy of the same type 
/// </summary> 
/// <typeparam name="T">The type of object to copy</typeparam> 
/// <param name="ObjectSource">The source object to copy</param> 
public T CopyObject<T>(T ObjectSource) 
{ 
    T NewObject = System.Activator.CreateInstance<T>(); 

    foreach (PropertyInfo p in ObjectSource.GetType().GetProperties()) 
     NewObject.GetType().GetProperty(p.Name).SetValue(NewObject, p.GetValue(ObjectSource, null), null); 

    return NewObject; 
} 
1

इस सीमा ने मुझे प्रभावित किया जब मैंने जेनेरिक प्रकारों के लिए ऑपरेटरों को अधिभारित करने की कोशिश की; चूंकि वहां कोई "अनौपचारिक" बाधा नहीं थी, और अन्य कारणों की आशंका के लिए स्टैक ओवरफ्लो पर अच्छे लोग प्रदान करने में प्रसन्न हैं, सामान्य प्रकारों पर संचालन को परिभाषित नहीं किया जा सकता है।

मैं की तरह

public struct Foo<T> 
{ 
    public T Value{ get; private set; } 

    public static Foo<T> operator +(Foo<T> LHS, Foo<T> RHS) 
    { 
     return new Foo<T> { Value = LHS.Value + RHS.Value; }; 
    } 
} 

मैं गतिशील क्रम टाइपिंग .net4 का उपयोग कर इस समस्या के काम किया है कुछ करना चाहता था। dynamic उपयोग के बारे में

public struct Foo<T> 
{ 
    public T Value { get; private set; } 

    public static Foo<T> operator +(Foo<T> LHS, Foo<T> RHS) 
    { 
     return new Foo<T> { Value = LHS.Value + (dynamic)RHS.Value }; 
    } 
} 

दो बातें

  1. प्रदर्शन कर रहे हैं। सभी मूल्य प्रकार बॉक्सिंग मिलता है।
  2. रनटाइम त्रुटियां। आप कंपाइलर को "हरा" देते हैं, लेकिन टाइप सुरक्षा को खो देते हैं। यदि जेनेरिक प्रकार में ऑपरेटर परिभाषित नहीं होता है, तो निष्पादन के दौरान एक अपवाद फेंक दिया जाएगा।
50

वर्कअराउंड का उपयोग कर नीतियों:

interface INumericPolicy<T> 
{ 
    T Zero(); 
    T Add(T a, T b); 
    // add more functions here, such as multiplication etc. 
} 

struct NumericPolicies: 
    INumericPolicy<int>, 
    INumericPolicy<long> 
    // add more INumericPolicy<> for different numeric types. 
{ 
    int INumericPolicy<int>.Zero() { return 0; } 
    long INumericPolicy<long>.Zero() { return 0; } 
    int INumericPolicy<int>.Add(int a, int b) { return a + b; } 
    long INumericPolicy<long>.Add(long a, long b) { return a + b; } 
    // implement all functions from INumericPolicy<> interfaces. 

    public static NumericPolicies Instance = new NumericPolicies(); 
} 

एल्गोरिदम:

static class Algorithms 
{ 
    public static T Sum<P, T>(this P p, params T[] a) 
     where P: INumericPolicy<T> 
    { 
     var r = p.Zero(); 
     foreach(var i in a) 
     { 
      r = p.Add(r, i); 
     } 
     return r; 
    } 

} 

उपयोग:

int i = NumericPolicies.Instance.Sum(1, 2, 3, 4, 5); 
long l = NumericPolicies.Instance.Sum(1L, 2, 3, 4, 5); 
NumericPolicies.Instance.Sum("www", "") // compile-time error. 

समाधान संकलन समय सुरक्षित है। CityLizard Framework .NET 4.0 के लिए संकलित संस्करण प्रदान करता है। फ़ाइल lib/NETFramework4.0/CityLizard.Policy.dll है।

यह नुजेट में भी उपलब्ध है: https://www.nuget.org/packages/CityLizard/CityLizard.Policy.I संरचना देखें।

+0

जेनेरिक पैरामीटर से कम फ़ंक्शन तर्क होने पर मुझे इस पैटर्न के साथ समस्याएं थीं। खोला गया http://stackoverflow.com/questions/36048248/implementing-multiparameter-c-template-like-behourour-on-c-sharp-using-policy – xvan

+0

'struct' का उपयोग करने का कोई कारण क्यों? क्या होगा यदि मैं इसके बजाय सिंगलटन-क्लास का उपयोग करता हूं और उदाहरण को 'सार्वजनिक स्थैतिक न्यूमेरिक पॉलिसीज इंस्टेंस = नई न्यूमेरिक पॉलिसीज();' में बदलता हूं और फिर इस कन्स्ट्रक्टर 'निजी न्यूमेरिक पॉलिसीज() {} 'को जोड़ता हूं। –

+0

@ एमकेज़ेमखरी आप सिंगलटन का उपयोग कर सकते हैं। मैं संरचना पसंद करते हैं। सिद्धांत रूप में, इसे संकलक/सीएलआर द्वारा अनुकूलित किया जा सकता है क्योंकि संरचना में कोई जानकारी नहीं है। सिंगलटन के मामले में, आप अभी भी एक संदर्भ पारित करेंगे, जो जीसी पर अतिरिक्त दबाव डाल सकता है। एक और फायदा यह है कि संरचना शून्य नहीं हो सकती है :-)। –

1

इसके लिए अभी तक कोई 'अच्छा' समाधान नहीं है। हालांकि आप अपने हाइपोटेटिकल 'अनौपचारिक' बाधा के लिए कई मिसाइलों को रद्द करने के लिए टाइप तर्क को संकीर्ण कर सकते हैं क्योंकि हैकड ने ऊपर दिखाया है।

स्थिर bool IntegerFunction < टी > (टी मूल्य) जहां टी: IComparable, IFormattable, IConvertible, IComparable < टी >, IEquatable < टी >, struct {...

1

.NET संख्यात्मक आदिम प्रकार किसी भी सामान्य इंटरफ़ेस को साझा नहीं करते हैं जो उन्हें गणना के लिए उपयोग करने की अनुमति देगा। अपने स्वयं के इंटरफेस को परिभाषित करना संभव होगा (उदाहरण के लिए ISignedWholeNumber) जो इस तरह के संचालन करेगा, संरचनाओं को परिभाषित करेगा जिसमें एक Int16, Int32 इत्यादि शामिल हैं और उन इंटरफेस को लागू करें, और फिर उन विधियों को स्वीकार करें जो ISignedWholeNumber तक सीमित सामान्य प्रकार स्वीकार करते हैं, लेकिन होने के कारण संख्यात्मक मानों को आपके संरचना प्रकारों में परिवर्तित करने के लिए संभवतः एक उपद्रव होगा।

एक वैकल्पिक दृष्टिकोण एक स्थिर संपत्ति bool Available {get;}; और Int64 GetInt64(T value), T FromInt64(Int64 value), bool TryStoreInt64(Int64 value, ref T dest) के लिए स्थिर प्रतिनिधियों के साथ स्थिर वर्ग Int64Converter<T> परिभाषित करने के लिए किया जाएगा। क्लास कन्स्ट्रक्टर ज्ञात प्रकारों के लिए प्रतिनिधियों को लोड करने के लिए हार्ड-कोडड का उपयोग कर सकता है, और संभवतया प्रतिबिंब का उपयोग यह जांचने के लिए करता है कि T उचित नामों और हस्ताक्षरों के साथ विधियों को लागू करता है (यदि यह ऐसी संरचना की तरह है जिसमें Int64 है और एक संख्या का प्रतिनिधित्व करता है, लेकिन एक कस्टम ToString() विधि है)। यह दृष्टिकोण संकलन-समय प्रकार-जांच से जुड़े फायदे खो देगा, लेकिन फिर भी मुक्केबाजी संचालन से बचने के लिए प्रबंधन करेगा और प्रत्येक प्रकार को केवल एक बार "चेक" करना होगा। इसके बाद, उस प्रकार से जुड़े संचालन को एक प्रतिनिधि प्रेषण के साथ बदल दिया जाएगा।

बजाय::

+0

'IConvertible' .. –

+0

@ केनकिन: आईकोनवर्टेबल एक माध्यम प्रदान करता है जिसके द्वारा किसी भी पूर्णांक को अन्य पूर्णांक प्रकार में जोड़ा जा सकता है उदाहरण के लिए एक 'Int64' परिणाम, लेकिन एक माध्यम प्रदान नहीं करता है जिसके द्वारा उदा। मनमानी प्रकार का एक पूर्णांक उसी प्रकार के एक और पूर्णांक * उत्पन्न करने के लिए बढ़ाया जा सकता है *। – supercat

3

मैं इन समस्याओं को हल करने के लिए थोड़ा पुस्तकालय कार्यक्षमता बनाया

public T DifficultCalculation<T>(T a, T b) 
{ 
    T result = a * b + a; // <== WILL NOT COMPILE! 
    return result; 
} 
Console.WriteLine(DifficultCalculation(2, 3)); // Should result in 8. 

आप लिख सकते हैं:

public T DifficultCalculation<T>(Number<T> a, Number<T> b) 
{ 
    Number<T> result = a * b + a; 
    return (T)result; 
} 
Console.WriteLine(DifficultCalculation(2, 3)); // Results in 8. 

आप यहाँ स्रोत कोड पा सकते हैं: https://codereview.stackexchange.com/questions/26022/improvement-requested-for-generic-calculator-and-generic-number

72

इस प्रश्न की लोकप्रियता को ध्यान में रखते हुए और इस तरह के एक समारोह के पीछे ब्याज मुझे आश्चर्य है कि अभी तक टी 4 शामिल कोई जवाब नहीं है।

इस नमूना कोड में मैं शक्तिशाली टेम्पलेटिंग इंजन का उपयोग करने के लिए एक बहुत ही सरल उदाहरण दिखाऊंगा कि संकलक जेनरिक के साथ दृश्यों के पीछे कितना करता है।

हुप्स के माध्यम से जाने और संकलन-समय निश्चितता बलिदान करने के बजाय आप केवल उस प्रकार का फ़ंक्शन जेनरेट कर सकते हैं जिसे आप पसंद करते हैं और उसके अनुसार (संकलन समय पर!) का उपयोग करें।

ऐसा करने में:

  • एक नया पाठ टेम्पलेट फ़ाइल GenericNumberMethodTemplate.tt बुलाया बनाएँ।
  • ऑटो-जेनरेट कोड हटाएं (आप इसे अधिकतर रखेंगे, लेकिन कुछ की आवश्यकता नहीं है)।
<#@ template language="C#" #> 
<#@ output extension=".cs" #> 
<#@ assembly name="System.Core" #> 

<# Type[] types = new[] { 
    typeof(Int16), typeof(Int32), typeof(Int64), 
    typeof(UInt16), typeof(UInt32), typeof(UInt64) 
    }; 
#> 

using System; 
public static class MaxMath { 
    <# foreach (var type in types) { 
    #> 
     public static <#= type.Name #> Max (<#= type.Name #> val1, <#= type.Name #> val2) { 
      return val1 > val2 ? val1 : val2; 
     } 
    <# 
    } #> 
} 

यह है कि:

  • निम्नलिखित स्निपेट जोड़ें। अब आप कर चुके हैं

    using System; 
    public static class MaxMath { 
        public static Int16 Max (Int16 val1, Int16 val2) { 
         return val1 > val2 ? val1 : val2; 
        } 
        public static Int32 Max (Int32 val1, Int32 val2) { 
         return val1 > val2 ? val1 : val2; 
        } 
        public static Int64 Max (Int64 val1, Int64 val2) { 
         return val1 > val2 ? val1 : val2; 
        } 
        public static UInt16 Max (UInt16 val1, UInt16 val2) { 
         return val1 > val2 ? val1 : val2; 
        } 
        public static UInt32 Max (UInt32 val1, UInt32 val2) { 
         return val1 > val2 ? val1 : val2; 
        } 
        public static UInt64 Max (UInt64 val1, UInt64 val2) { 
         return val1 > val2 ? val1 : val2; 
        } 
    } 
    

    अपने main विधि में आप सत्यापित कर सकते आप संकलन समय निश्चितता है:

    namespace TTTTTest 
    { 
        class Program 
        { 
         static void Main(string[] args) 
         { 
          long val1 = 5L; 
          long val2 = 10L; 
          Console.WriteLine(MaxMath.Max(val1, val2)); 
          Console.Read(); 
         } 
        } 
    } 
    

    enter image description here

    इस फाइल को सहेजा जा रहा है स्वचालित रूप से इसे इस स्रोत फ़ाइल को संकलित कर देगा मैं एक टिप्पणी से आगे जाऊंगा: नहीं, यह DRY सिद्धांत का उल्लंघन नहीं है। डीआरवाई सिद्धांत लोगों को कई जगहों पर कोड डुप्लिकेट करने से रोकने के लिए है जो अनुप्रयोग को बनाए रखने के लिए कठिन हो जाएगा।

    यह बिल्कुल भी मामला नहीं है: यदि आप कोई परिवर्तन चाहते हैं तो आप केवल टेम्पलेट (अपनी पीढ़ी के लिए एक स्रोत!) बदल सकते हैं और यह हो गया है।

    आदेश, अपने स्वयं के कस्टम परिभाषा के साथ इसका इस्तेमाल करने के लिए एक नाम स्थान घोषणा जोड़ने अपने तैयार किए गए कोड और partial के रूप में वर्ग निशान (यकीन है कि यह एक जहाँ आप अपने खुद के कार्यान्वयन को परिभाषित करेंगे के रूप में ही एक है कर) में। बाद में, अपने टेम्पलेट फ़ाइल में ये पंक्तियां जोड़ सकते हैं ताकि यह अंतिम संकलन में शामिल किया जाएगा:

    <#@ import namespace="TheNameSpaceYouWillUse" #> 
    <#@ assembly name="$(TargetPath)" #> 
    

    के ईमानदार होना चलो: यह बहुत अच्छा है।

    अस्वीकरण: यह नमूना Metaprogramming in .NET by Kevin Hazzard and Jason Bock, Manning Publications से काफी प्रभावित हुआ है।

  • +0

    यह बहुत अच्छा है, लेकिन क्या इस समाधान को संशोधित करना संभव होगा कि विधियों को कुछ सामान्य प्रकार 'टी' को स्वीकार किया जाए जो विभिन्न 'इंटेक्स' वर्गों से प्राप्त हो या प्राप्त हो? मुझे यह समाधान पसंद है क्योंकि यह समय बचाता है, लेकिन इसके लिए इस मुद्दे को हल करने के लिए 100% (जैसा कि सी # को इस प्रकार की बाधा के लिए समर्थन था, अंतर्निहित नहीं होने के बावजूद) प्रत्येक उत्पन्न जेनरेटेड विधियों को अभी भी सामान्य होना चाहिए ताकि वे एक प्रकार की वस्तु को वापस कर सकते हैं जो 'IntXX' कक्षाओं में से एक से प्राप्त होता है। –

    +0

    @ZacharyKniebel: इस समाधान के पीछे पूरा विचार यह है कि आप एक सामान्य प्रकार नहीं बनाते हैं। दृश्यों के पीछे क्या एक सामान्य विधि है (मोटे तौर पर) इस तरह एक विधि बना रही है: यह जेनेरिक पैरामीटर को वास्तविक प्रकार से बदल देती है और इसका उपयोग करती है। एक सामान्य विधि संख्यात्मक प्रकारों में पारित प्रकार पर बाधाओं को लागू करना चाहती है और फिर ठोस प्रकार के साथ वास्तविक कार्यान्वयन बनाती है।यहां हम उस भाग को छोड़ देते हैं और तुरंत ठोस प्रकार बनाते हैं: आपको बस इतना करना है कि आप अपनी सूची में टेम्पलेट फ़ाइल में अपनी पसंद के अनुसार जोड़ना चाहते हैं और इसे कंक्रीट प्रकार –

    +0

    उत्पन्न करने दें, मैं अपने ज्ञान की सीमा के करीब कैसे हूं प्रकार संकलित किए जाते हैं, इसलिए अगर मैं गलत हूं, तो मैं क्षमा चाहता हूं, लेकिन अगर एक सामान्य प्रकार दृश्यों के पीछे इन सभी विधियों को उत्पन्न करता है, तो यह बाध्य प्रकारों से प्राप्त होने वाली सभी कक्षाओं को ढूंढकर ऐसा नहीं करना चाहिए, और इसी तरह की विधि उत्पन्न करना से प्रत्येक? दूसरे शब्दों में, क्या यह उन सभी वर्गों की तलाश नहीं करेगा जो प्रत्येक 'IntXX' प्रकारों से प्राप्त होते हैं? यदि मैं सही हूं, तो क्या आपका समाधान वांछित समाधान से कम नहीं होगा क्योंकि यह वर्तमान स्थिति में विरासत वाले प्रकारों के लिए खाता नहीं है? –

    4

    टेम्पलेट्स को प्रकारों को प्रतिबंधित करने का कोई तरीका नहीं है, लेकिन आप इस प्रकार के आधार पर विभिन्न कार्रवाइयां परिभाषित कर सकते हैं। एक सामान्य संख्यात्मक पैकेज के हिस्से के रूप में, मुझे दो मान जोड़ने के लिए एक सामान्य वर्ग की आवश्यकता थी।

    class Something<TCell> 
        { 
         internal static TCell Sum(TCell first, TCell second) 
         { 
          if (typeof(TCell) == typeof(int)) 
           return (TCell)((object)(((int)((object)first)) + ((int)((object)second)))); 
    
          if (typeof(TCell) == typeof(double)) 
           return (TCell)((object)(((double)((object)first)) + ((double)((object)second)))); 
    
          return second; 
         } 
        } 
    

    ध्यान दें कि typeofs संकलन समय पर मूल्यांकन किया जाता है, इसलिए बयान संकलक द्वारा हटाया जा होगा। कंपाइलर भी नकली जानवरों को हटा देता है। तो कुछ

     internal static int Sum(int first, int second) 
         { 
          return first + second; 
         } 
    
    +0

    एक अनुभवजन्य समाधान प्रदान करने के लिए धन्यवाद! – zsf222

    1

    को संकलक में हल होगा आप .NET 4.0 उपयोग कर रहे हैं और बाद में तो तुम सिर्फ क्रम में विधि तर्क के रूप में गतिशील का उपयोग करें और जांच कर सकते हैं कि पारित कर दिया गतिशील तर्क प्रकार है संख्यात्मक/पूर्णांक प्रकार।

    यदि पारित गतिशील के प्रकार है नहीं सांख्यिक/पूर्णांक प्रकार तो अपवाद फेंक देते हैं।

    using System; 
    public class InvalidArgumentException : Exception 
    { 
        public InvalidArgumentException(string message) : base(message) {} 
    } 
    public class InvalidArgumentTypeException : InvalidArgumentException 
    { 
        public InvalidArgumentTypeException(string message) : base(message) {} 
    } 
    public class ArgumentTypeNotIntegerException : InvalidArgumentTypeException 
    { 
        public ArgumentTypeNotIntegerException(string message) : base(message) {} 
    } 
    public static class Program 
    { 
        private static bool IntegerFunction(dynamic n) 
        { 
         if (n.GetType() != typeof(Int16) && 
          n.GetType() != typeof(Int32) && 
          n.GetType() != typeof(Int64) && 
          n.GetType() != typeof(UInt16) && 
          n.GetType() != typeof(UInt32) && 
          n.GetType() != typeof(UInt64)) 
          throw new ArgumentTypeNotIntegerException("argument type is not integer type"); 
         //code that implements IntegerFunction goes here 
        } 
        private static void Main() 
        { 
         Console.WriteLine("{0}",IntegerFunction(0)); //Compiles, no run time error and first line of output buffer is either "True" or "False" depends on the code that implements "Program.IntegerFunction" static method. 
         Console.WriteLine("{0}",IntegerFunction("string")); //Also compiles but it is run time error and exception of type "ArgumentTypeNotIntegerException" is thrown here. 
         Console.WriteLine("This is the last Console.WriteLine output"); //Never reached and executed due the run time error and the exception thrown on the second line of Program.Main static method. 
        } 
    

    बेशक कि इस समाधान केवल लेकिन कभी संकलन समय में रन टाइम में काम करता है:

    एक उदाहरण कम कोड है कि इस विचार को लागू करता है की तरह कुछ है।

    आप एक समाधान है कि हमेशा संकलन समय में काम करता है और चलाने के समय में कभी नहीं चाहते हैं तो आपको एक सार्वजनिक struct/वर्ग जिसका अतिभारित सार्वजनिक कंस्ट्रक्टर्स वांछित प्रकार के तर्क को स्वीकार ही और साथ गतिशील रैप करने के लिए होगा संरचना/कक्षा उचित नाम दें।

    यह भावना है कि लिपटे गतिशील हमेशा वर्ग/struct के निजी सदस्य है बनाता है और यह struct/वर्ग के एकमात्र सदस्य और struct के एकमात्र सदस्य का नाम है/वर्ग "मूल्य है "।

    तुम भी परिभाषित करने और सार्वजनिक विधियों और/या ऑपरेटरों उस वर्ग/struct यदि आवश्यक हो तो के निजी गतिशील सदस्य के लिए वांछित प्रकार के साथ काम को लागू करना होगा।

    यह भी समझ में आता है struct/वर्ग विशेष/अद्वितीय निर्माता है कि तर्क है कि आरंभ में यह "मूल्य" कहा जाता है केवल निजी गतिशील सदस्य लेकिन इस निर्माता की संशोधक के रूप में गतिशील स्वीकार करता है कि निजी है बेशक।

    एक बार कक्षा/संरचना तैयार होने के बाद तर्क के प्रकार को इंटीजर फ़ंक्शन को परिभाषित किया गया है जिसे परिभाषित किया गया है।

    एक उदाहरण लंबे कोड है कि इस विचार को लागू करता है कुछ की तरह:

    using System; 
    public struct Integer 
    { 
        private dynamic value; 
        private Integer(dynamic n) { this.value = n; } 
        public Integer(Int16 n) { this.value = n; } 
        public Integer(Int32 n) { this.value = n; } 
        public Integer(Int64 n) { this.value = n; } 
        public Integer(UInt16 n) { this.value = n; } 
        public Integer(UInt32 n) { this.value = n; } 
        public Integer(UInt64 n) { this.value = n; } 
        public Integer(Integer n) { this.value = n.value; } 
        public static implicit operator Int16(Integer n) { return n.value; } 
        public static implicit operator Int32(Integer n) { return n.value; } 
        public static implicit operator Int64(Integer n) { return n.value; } 
        public static implicit operator UInt16(Integer n) { return n.value; } 
        public static implicit operator UInt32(Integer n) { return n.value; } 
        public static implicit operator UInt64(Integer n) { return n.value; } 
        public static Integer operator +(Integer x, Int16 y) { return new Integer(x.value + y); } 
        public static Integer operator +(Integer x, Int32 y) { return new Integer(x.value + y); } 
        public static Integer operator +(Integer x, Int64 y) { return new Integer(x.value + y); } 
        public static Integer operator +(Integer x, UInt16 y) { return new Integer(x.value + y); } 
        public static Integer operator +(Integer x, UInt32 y) { return new Integer(x.value + y); } 
        public static Integer operator +(Integer x, UInt64 y) { return new Integer(x.value + y); } 
        public static Integer operator -(Integer x, Int16 y) { return new Integer(x.value - y); } 
        public static Integer operator -(Integer x, Int32 y) { return new Integer(x.value - y); } 
        public static Integer operator -(Integer x, Int64 y) { return new Integer(x.value - y); } 
        public static Integer operator -(Integer x, UInt16 y) { return new Integer(x.value - y); } 
        public static Integer operator -(Integer x, UInt32 y) { return new Integer(x.value - y); } 
        public static Integer operator -(Integer x, UInt64 y) { return new Integer(x.value - y); } 
        public static Integer operator *(Integer x, Int16 y) { return new Integer(x.value * y); } 
        public static Integer operator *(Integer x, Int32 y) { return new Integer(x.value * y); } 
        public static Integer operator *(Integer x, Int64 y) { return new Integer(x.value * y); } 
        public static Integer operator *(Integer x, UInt16 y) { return new Integer(x.value * y); } 
        public static Integer operator *(Integer x, UInt32 y) { return new Integer(x.value * y); } 
        public static Integer operator *(Integer x, UInt64 y) { return new Integer(x.value * y); } 
        public static Integer operator /(Integer x, Int16 y) { return new Integer(x.value/y); } 
        public static Integer operator /(Integer x, Int32 y) { return new Integer(x.value/y); } 
        public static Integer operator /(Integer x, Int64 y) { return new Integer(x.value/y); } 
        public static Integer operator /(Integer x, UInt16 y) { return new Integer(x.value/y); } 
        public static Integer operator /(Integer x, UInt32 y) { return new Integer(x.value/y); } 
        public static Integer operator /(Integer x, UInt64 y) { return new Integer(x.value/y); } 
        public static Integer operator %(Integer x, Int16 y) { return new Integer(x.value % y); } 
        public static Integer operator %(Integer x, Int32 y) { return new Integer(x.value % y); } 
        public static Integer operator %(Integer x, Int64 y) { return new Integer(x.value % y); } 
        public static Integer operator %(Integer x, UInt16 y) { return new Integer(x.value % y); } 
        public static Integer operator %(Integer x, UInt32 y) { return new Integer(x.value % y); } 
        public static Integer operator %(Integer x, UInt64 y) { return new Integer(x.value % y); } 
        public static Integer operator +(Integer x, Integer y) { return new Integer(x.value + y.value); } 
        public static Integer operator -(Integer x, Integer y) { return new Integer(x.value - y.value); } 
        public static Integer operator *(Integer x, Integer y) { return new Integer(x.value * y.value); } 
        public static Integer operator /(Integer x, Integer y) { return new Integer(x.value/y.value); } 
        public static Integer operator %(Integer x, Integer y) { return new Integer(x.value % y.value); } 
        public static bool operator ==(Integer x, Int16 y) { return x.value == y; } 
        public static bool operator !=(Integer x, Int16 y) { return x.value != y; } 
        public static bool operator ==(Integer x, Int32 y) { return x.value == y; } 
        public static bool operator !=(Integer x, Int32 y) { return x.value != y; } 
        public static bool operator ==(Integer x, Int64 y) { return x.value == y; } 
        public static bool operator !=(Integer x, Int64 y) { return x.value != y; } 
        public static bool operator ==(Integer x, UInt16 y) { return x.value == y; } 
        public static bool operator !=(Integer x, UInt16 y) { return x.value != y; } 
        public static bool operator ==(Integer x, UInt32 y) { return x.value == y; } 
        public static bool operator !=(Integer x, UInt32 y) { return x.value != y; } 
        public static bool operator ==(Integer x, UInt64 y) { return x.value == y; } 
        public static bool operator !=(Integer x, UInt64 y) { return x.value != y; } 
        public static bool operator ==(Integer x, Integer y) { return x.value == y.value; } 
        public static bool operator !=(Integer x, Integer y) { return x.value != y.value; } 
        public override bool Equals(object obj) { return this == (Integer)obj; } 
        public override int GetHashCode() { return this.value.GetHashCode(); } 
        public override string ToString() { return this.value.ToString(); } 
        public static bool operator >(Integer x, Int16 y) { return x.value > y; } 
        public static bool operator <(Integer x, Int16 y) { return x.value < y; } 
        public static bool operator >(Integer x, Int32 y) { return x.value > y; } 
        public static bool operator <(Integer x, Int32 y) { return x.value < y; } 
        public static bool operator >(Integer x, Int64 y) { return x.value > y; } 
        public static bool operator <(Integer x, Int64 y) { return x.value < y; } 
        public static bool operator >(Integer x, UInt16 y) { return x.value > y; } 
        public static bool operator <(Integer x, UInt16 y) { return x.value < y; } 
        public static bool operator >(Integer x, UInt32 y) { return x.value > y; } 
        public static bool operator <(Integer x, UInt32 y) { return x.value < y; } 
        public static bool operator >(Integer x, UInt64 y) { return x.value > y; } 
        public static bool operator <(Integer x, UInt64 y) { return x.value < y; } 
        public static bool operator >(Integer x, Integer y) { return x.value > y.value; } 
        public static bool operator <(Integer x, Integer y) { return x.value < y.value; } 
        public static bool operator >=(Integer x, Int16 y) { return x.value >= y; } 
        public static bool operator <=(Integer x, Int16 y) { return x.value <= y; } 
        public static bool operator >=(Integer x, Int32 y) { return x.value >= y; } 
        public static bool operator <=(Integer x, Int32 y) { return x.value <= y; } 
        public static bool operator >=(Integer x, Int64 y) { return x.value >= y; } 
        public static bool operator <=(Integer x, Int64 y) { return x.value <= y; } 
        public static bool operator >=(Integer x, UInt16 y) { return x.value >= y; } 
        public static bool operator <=(Integer x, UInt16 y) { return x.value <= y; } 
        public static bool operator >=(Integer x, UInt32 y) { return x.value >= y; } 
        public static bool operator <=(Integer x, UInt32 y) { return x.value <= y; } 
        public static bool operator >=(Integer x, UInt64 y) { return x.value >= y; } 
        public static bool operator <=(Integer x, UInt64 y) { return x.value <= y; } 
        public static bool operator >=(Integer x, Integer y) { return x.value >= y.value; } 
        public static bool operator <=(Integer x, Integer y) { return x.value <= y.value; } 
        public static Integer operator +(Int16 x, Integer y) { return new Integer(x + y.value); } 
        public static Integer operator +(Int32 x, Integer y) { return new Integer(x + y.value); } 
        public static Integer operator +(Int64 x, Integer y) { return new Integer(x + y.value); } 
        public static Integer operator +(UInt16 x, Integer y) { return new Integer(x + y.value); } 
        public static Integer operator +(UInt32 x, Integer y) { return new Integer(x + y.value); } 
        public static Integer operator +(UInt64 x, Integer y) { return new Integer(x + y.value); } 
        public static Integer operator -(Int16 x, Integer y) { return new Integer(x - y.value); } 
        public static Integer operator -(Int32 x, Integer y) { return new Integer(x - y.value); } 
        public static Integer operator -(Int64 x, Integer y) { return new Integer(x - y.value); } 
        public static Integer operator -(UInt16 x, Integer y) { return new Integer(x - y.value); } 
        public static Integer operator -(UInt32 x, Integer y) { return new Integer(x - y.value); } 
        public static Integer operator -(UInt64 x, Integer y) { return new Integer(x - y.value); } 
        public static Integer operator *(Int16 x, Integer y) { return new Integer(x * y.value); } 
        public static Integer operator *(Int32 x, Integer y) { return new Integer(x * y.value); } 
        public static Integer operator *(Int64 x, Integer y) { return new Integer(x * y.value); } 
        public static Integer operator *(UInt16 x, Integer y) { return new Integer(x * y.value); } 
        public static Integer operator *(UInt32 x, Integer y) { return new Integer(x * y.value); } 
        public static Integer operator *(UInt64 x, Integer y) { return new Integer(x * y.value); } 
        public static Integer operator /(Int16 x, Integer y) { return new Integer(x/y.value); } 
        public static Integer operator /(Int32 x, Integer y) { return new Integer(x/y.value); } 
        public static Integer operator /(Int64 x, Integer y) { return new Integer(x/y.value); } 
        public static Integer operator /(UInt16 x, Integer y) { return new Integer(x/y.value); } 
        public static Integer operator /(UInt32 x, Integer y) { return new Integer(x/y.value); } 
        public static Integer operator /(UInt64 x, Integer y) { return new Integer(x/y.value); } 
        public static Integer operator %(Int16 x, Integer y) { return new Integer(x % y.value); } 
        public static Integer operator %(Int32 x, Integer y) { return new Integer(x % y.value); } 
        public static Integer operator %(Int64 x, Integer y) { return new Integer(x % y.value); } 
        public static Integer operator %(UInt16 x, Integer y) { return new Integer(x % y.value); } 
        public static Integer operator %(UInt32 x, Integer y) { return new Integer(x % y.value); } 
        public static Integer operator %(UInt64 x, Integer y) { return new Integer(x % y.value); } 
        public static bool operator ==(Int16 x, Integer y) { return x == y.value; } 
        public static bool operator !=(Int16 x, Integer y) { return x != y.value; } 
        public static bool operator ==(Int32 x, Integer y) { return x == y.value; } 
        public static bool operator !=(Int32 x, Integer y) { return x != y.value; } 
        public static bool operator ==(Int64 x, Integer y) { return x == y.value; } 
        public static bool operator !=(Int64 x, Integer y) { return x != y.value; } 
        public static bool operator ==(UInt16 x, Integer y) { return x == y.value; } 
        public static bool operator !=(UInt16 x, Integer y) { return x != y.value; } 
        public static bool operator ==(UInt32 x, Integer y) { return x == y.value; } 
        public static bool operator !=(UInt32 x, Integer y) { return x != y.value; } 
        public static bool operator ==(UInt64 x, Integer y) { return x == y.value; } 
        public static bool operator !=(UInt64 x, Integer y) { return x != y.value; } 
        public static bool operator >(Int16 x, Integer y) { return x > y.value; } 
        public static bool operator <(Int16 x, Integer y) { return x < y.value; } 
        public static bool operator >(Int32 x, Integer y) { return x > y.value; } 
        public static bool operator <(Int32 x, Integer y) { return x < y.value; } 
        public static bool operator >(Int64 x, Integer y) { return x > y.value; } 
        public static bool operator <(Int64 x, Integer y) { return x < y.value; } 
        public static bool operator >(UInt16 x, Integer y) { return x > y.value; } 
        public static bool operator <(UInt16 x, Integer y) { return x < y.value; } 
        public static bool operator >(UInt32 x, Integer y) { return x > y.value; } 
        public static bool operator <(UInt32 x, Integer y) { return x < y.value; } 
        public static bool operator >(UInt64 x, Integer y) { return x > y.value; } 
        public static bool operator <(UInt64 x, Integer y) { return x < y.value; } 
        public static bool operator >=(Int16 x, Integer y) { return x >= y.value; } 
        public static bool operator <=(Int16 x, Integer y) { return x <= y.value; } 
        public static bool operator >=(Int32 x, Integer y) { return x >= y.value; } 
        public static bool operator <=(Int32 x, Integer y) { return x <= y.value; } 
        public static bool operator >=(Int64 x, Integer y) { return x >= y.value; } 
        public static bool operator <=(Int64 x, Integer y) { return x <= y.value; } 
        public static bool operator >=(UInt16 x, Integer y) { return x >= y.value; } 
        public static bool operator <=(UInt16 x, Integer y) { return x <= y.value; } 
        public static bool operator >=(UInt32 x, Integer y) { return x >= y.value; } 
        public static bool operator <=(UInt32 x, Integer y) { return x <= y.value; } 
        public static bool operator >=(UInt64 x, Integer y) { return x >= y.value; } 
        public static bool operator <=(UInt64 x, Integer y) { return x <= y.value; } 
    } 
    public static class Program 
    { 
        private static bool IntegerFunction(Integer n) 
        { 
         //code that implements IntegerFunction goes here 
         //note that there is NO code that checks the type of n in rum time, because it is NOT needed anymore 
        } 
        private static void Main() 
        { 
         Console.WriteLine("{0}",IntegerFunction(0)); //compile error: there is no overloaded METHOD for objects of type "int" and no implicit conversion from any object, including "int", to "Integer" is known. 
         Console.WriteLine("{0}",IntegerFunction(new Integer(0))); //both compiles and no run time error 
         Console.WriteLine("{0}",IntegerFunction("string")); //compile error: there is no overloaded METHOD for objects of type "string" and no implicit conversion from any object, including "string", to "Integer" is known. 
         Console.WriteLine("{0}",IntegerFunction(new Integer("string"))); //compile error: there is no overloaded CONSTRUCTOR for objects of type "string" 
        } 
    } 
    

    नोट करें कि अपने कोड में गतिशील का उपयोग करने के आप Microsoft.CSharp के लिए संदर्भ जोड़े चाहिए

    यदि .NET ढांचे का संस्करण 4.0/गतिशील से नीचे/नीचे/कम है, तो undefi है उस संस्करण में ned तो आपको ऑब्जेक्ट का उपयोग करना होगा और पूर्णांक प्रकार को कास्टिंग करना होगा, जो मुसीबत है, इसलिए मैं अनुशंसा करता हूं कि आप कम से कम .NET 4.0 या नए का उपयोग करें यदि आप ऐसा कर सकते हैं तो आप गतिशील का उपयोग कर सकते हैं ऑब्जेक्ट

    संबंधित मुद्दे

     संबंधित मुद्दे