दिलचस्प पोस्ट
JSON के लिए जावास्क्रिप्ट एसोसिएटिव सरणी प्रोग्राम कीबोर्ड के शीर्ष पर एक टूलबार संरेखित करें ट्यूपल तुलना पायथन में कैसे काम करता है? एक जार फ़ाइल में रिलीज को मर्ज करने का सबसे आसान तरीका Virtualenv या buildout का उपयोग कर पीआईआई की स्थापना के साथ समस्या जावास्क्रिप्ट "नए सरणी (एन)" और "अर्रे.प्रोटोटाइप.मैप" विरदीपन पायथन स्ट्रेटम () और समयक्षेत्र? कैसे django टेम्पलेट में शब्दकोश तत्व का उपयोग करने के लिए? सेलेनियम – पायथन – ड्रॉप-डाउन मेनू विकल्प मान Jquery के सामान्य और स्लिम पैकेज के बीच अंतर क्या हैं? कस्टम फ़ॉन्ट और XML लेआउट (एंड्रॉइड) पी के साथ डेटाबेस से गतिशील छवि प्रदर्शित करें: ग्राफिक इमेज और स्ट्रीमेड कंटेंट मैं मास्टर / मूल के साथ अलग सिर कैसे सम्मिलित कर सकता हूं? TypeScript किसी भी बनाम ऑब्जेक्ट जीआईटी चेरी-पिक बनाम मर्ज वर्कफ़्लो

क्या कोई बाधा है जो मेरी सामान्य पद्धति को संख्यात्मक प्रकारों पर रोक देती है?

क्या कोई मुझे बता सकता है कि जेनेरिक के साथ एक सामान्य प्रकार तर्क केवल सीमित करने के लिए एक तरीका है:

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

मुझे पता है कि कीवर्ड where , लेकिन इन प्रकारों के लिए इंटरफ़ेस नहीं मिल सकता है,

कुछ इस तरह:

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

वेब के समाधान से एकत्रित समाधान "क्या कोई बाधा है जो मेरी सामान्य पद्धति को संख्यात्मक प्रकारों पर रोक देती है?"

हेजल्बर्ग ने ब्रूस एकल के साथ एक साक्षात्कार में इस सुविधा को लागू नहीं करने के कारणों का वर्णन किया है

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

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

मैं आगे जाऊँगा और कहूँगा कि हमें ज़रूरत है

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

या और भी

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

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

आप कुछ और में नंबर लपेट कर सकते हैं ( INullable<T> समान) यहां पर codeproject पर ।


आप रनटाइम पर प्रतिबंध लागू कर सकते हैं (ऑपरेटर के लिए प्रतिबिंबित करके या प्रकारों की जांच के लिए), लेकिन इससे पहली जगह में जेनेरिक होने का फायदा कम हो सकता है

इस प्रश्न की लोकप्रियता को ध्यान में रखते हुए और इस तरह के एक समारोह के पीछे रूचि को देखते हुए मुझे आश्चर्य हुआ कि टी 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(); } } } 

यहां छवि विवरण दर्ज करें

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

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

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

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

आइए ईमानदारी से: यह बहुत अच्छा है

अस्वीकरण: इस नमूना को मेटाप्रोग्रामिंग द्वारा केविन हाज़र्ड और जेसन बोक द्वारा मैन्युअल प्रकाशन से काफी प्रभावित किया गया है।

नीतियों का उपयोग कर वैकल्पिक हल:

 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 फ्रेमवर्क .NET 4.0 के लिए संकलित संस्करण प्रदान करता है। फ़ाइल को lib / NETFramework4.0 / CityLizard.Policy.dll है।

अपडेट 2: कोड अपडेट किया जाता है, इसलिए इसे संकलित किया जा सकता है।

अपडेट 3: न्यूजेट में: https://www.nuget.org/packages/CityLizard/ CityLizard.Policy.I संरचना देखें

अपडेट 4: 'सभी। पी' को 'न्यूमेरिक नीतियों। इंस्ट्रेंस' में बदल दें।

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

क्या आप .NET का संस्करण का उपयोग कर रहे हैं? यदि आप .NET 3.5 का उपयोग कर रहे हैं, तो मेरे पास MiscUtil (निःशुल्क आदि) में एक जेनेरिक ऑपरेटर कार्यान्वयन है।

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

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

यह क्यों मुश्किल है पर कुछ अतिरिक्त पृष्ठभूमि यहाँ है ।

आप यह भी जानना चाह सकते हैं कि dynamic (4.0) सॉर्ट-इन इस मुद्दे को अप्रत्यक्ष रूप से हल करता है – अर्थात

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

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

मुझे लगता है कि एकमात्र हल एक रनटाइम चेक करना है जो दुर्भाग्य से संकलन के समय समस्या को रोकता है। ऐसा कुछ जाना था: –

 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... } 

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

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

संभवत: आप जितना करीब हो सकते हैं

 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> 

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

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

  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; } } 

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

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

मैंने इन समस्याओं को हल करने के लिए एक छोटी लाइब्रेरी कार्यक्षमता बनाई है:

के बजाय:

 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

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

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

यदि आप .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. } 

बेशक यह समाधान केवल चलाने के समय में काम करता है, लेकिन कभी संकलन समय में नहीं।

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

यह समझ में आता है कि लिपटे गतिशील हमेशा वर्ग / संरचना का निजी सदस्य है और यह संरचना / वर्ग का एकमात्र सदस्य है और संरचना / वर्ग के एकमात्र सदस्य का नाम "मान" है।

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

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

एक बार क्लास / स्ट्रेट तैयार हो जाता है तो तर्क के प्रकार की परिभाषा को परिभाषित किया जाता है जो उस श्रेणी / स्ट्रेट के रूप में परिभाषित किया जाता है।

इस विचार को कार्यान्वित करने वाला एक लंबा लंबा कोड कुछ ऐसा है:

 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" } } 

Note that in order to use dynamic in your code you must Add Reference to Microsoft.CSharp

If the version of the .NET framework is below/under/lesser than 4.0 and dynamic is undefined in that version then you will have to use object instead and do casting to the integer type, which is trouble, so I recommend that you use at least .NET 4.0 or newer if you can so you can use dynamic instead of object .

What is the point of the exercise?

As people pointed out already, you could have a non-generic function taking the largest item, and compiler will automatically convert up smaller ints for you.

 static bool IntegerFunction(Int64 value) { } 

If your function is on performance-critical path (very unlikely, IMO), you could provide overloads for all needed functions.

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

I would use a generic one which you could handle 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; } 

This limitation affected me when I tried to overload operators for generic types; since there was no "INumeric" constraint, and for a bevy of other reasons the good people on stackoverflow are happy to provide, operations cannot be defined on generic types.

I wanted something like

 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; }; } } 

I have worked around this issue using .net4 dynamic runtime typing.

 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 }; } } 

The two things about using dynamic are

  1. Performance. All value types get boxed.
  2. Runtime errors. You "beat" the compiler, but lose type safety. If the generic type doesn't have the operator defined, an exception will be thrown during execution.

There is no 'good' solution for this yet. However you can narrow the type argument significantly to rule out many missfits for your hypotetical 'INumeric' constraint as Haacked has shown above.

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

The .NET numeric primitive types do not share any common interface that would allow them to be used for calculations. It would be possible to define your own interfaces (eg ISignedWholeNumber ) which would perform such operations, define structures which contain a single Int16 , Int32 , etc. and implement those interfaces, and then have methods which accept generic types constrained to ISignedWholeNumber , but having to convert numeric values to your structure types would likely be a nuisance.

An alternative approach would be to define static class Int64Converter<T> with a static property bool Available {get;}; and static delegates for Int64 GetInt64(T value) , T FromInt64(Int64 value) , bool TryStoreInt64(Int64 value, ref T dest) . The class constructor could use be hard-coded to load delegates for known types, and possibly use Reflection to test whether type T implements methods with the proper names and signatures (in case it's something like a struct which contains an Int64 and represents a number, but has a custom ToString() method). This approach would lose the advantages associated with compile-time type-checking, but would still manage to avoid boxing operations and each type would only have to be "checked" once. After that, operations associated with that type would be replaced with a delegate dispatch.

There is no single interface or base class that they all inherit (that is not also inherited by other classes) so the simple answer is no.

I do wonder why this is an issue though. What are you wanting to do inside your IntegerFunction class that can only be done to integers?

I think you are misunderstanding generics. If the operation you are trying to perform is only good for specific data types then you are not doing something "generic".

Also, since you are only wanting to allow the function to work on int data types then you shouldn't need a separate function for each specific size. Simply taking a parameter in the largest specific type will allow the program to automatically upcast the smaller data types to it. (ie passing an Int16 will auto-convert to Int64 when calling).

If you are performing different operations based on the actual size of int being passed into the function then I would think you should seriously reconsider even trying to do what you are doing. If you have to fool the language you should think a bit more about what you are trying to accomplish rather than how to do what you want.

Failing all else, a parameter of type Object could be used and then you will have to check the type of the parameter and take appropriate action or throw an exception.