दिलचस्प पोस्ट
जावा में एक्स + + और ++ एक्स के बीच क्या कोई अंतर है? jQuery को चेक बॉक्स के सरणी में मान मिलता है जावास्क्रिप्ट में लूप के साथ ईवेंट हैंडलर्स कैसे उत्पन्न करें? प्रथम पृष्ठ लोड के बाद एक बार पृष्ठ ताज़ा करें एंड्रॉइड 4.2 पर एन्क्रिप्शन त्रुटि उप-दृश्यों के लिए दृश्यविकल्प चेतावनी: mysql_fetch_array () पैरामीटर 1 को संसाधन होने की उम्मीद है, बुलियन में दिया गया है स्ट्रिंग सरणी में स्ट्रिंग में स्ट्रिंग की जांच करने के लिए C # का उपयोग करना गतिशील रूप से एसएएस डेटा चरण से मैक्रो को कॉल करें Java का उपयोग करके एन्क्रिप्ट करता एन्कोडेड स्ट्रिंग को एन्क्रिप्ट करता है जो कि openssl aes-128-cbc से है? पीएसएस सरल एक्सएमएल के साथ XML नामस्थान पार्स करें समय के लिए कई असफल लॉगिन के लिए अनुरोध को ब्लॉक करें इकाई फ़्रेमवर्क में डेटाबेस टाइमआउट सेट करें रेस्ट कुंजीट के साथ विदेशी कुंजी संबंध मानचित्रण डिफ़ॉल्ट हैश एल्गोरिथम क्या है जो ASP.NET सदस्यता का उपयोग करता है?

सी # में सामान्य श्रेणी के लिए अंकगणितीय ऑपरेटर ओवरलोडिंग

जैसे एक सामान्य श्रेणी की परिभाषा को देखते हुए

public class ConstrainedNumber<T> : IEquatable<ConstrainedNumber<T>>, IEquatable<T>, IComparable<ConstrainedNumber<T>>, IComparable<T>, IComparable where T:struct, IComparable, IComparable<T>, IEquatable<T> 

मैं इसके लिए अंकगणित ऑपरेटरों को कैसे परिभाषित कर सकता हूं?

निम्नलिखित संकलन नहीं है, क्योंकि '+' ऑपरेटर प्रकार 'टी' और 'टी' पर लागू नहीं किया जा सकता है:

 public static T operator +( ConstrainedNumber<T> x, ConstrainedNumber<T> y) { return x._value + y._value; } 

सामान्य प्रकार 'टी' को 'जहां' कीवर्ड जैसा आप देख सकते हैं, के साथ विवश है, लेकिन मुझे अंक प्रकारों के लिए एक बाधा की आवश्यकता है जो अंकगणित ऑपरेटरों (IArithmetic?) हैं।

'टी' एक प्रारंभिक संख्या प्रकार जैसे इंट, फ्लोट, आदि होगा। क्या इस तरह के प्रकार के लिए 'जहां' बाधा है?

Solutions Collecting From Web of "सी # में सामान्य श्रेणी के लिए अंकगणितीय ऑपरेटर ओवरलोडिंग"

मुझे लगता है कि सबसे अच्छा आप करने में सक्षम होंगे IConvertible एक बाधा के रूप में उपयोग करें और ऐसा कुछ करें:

  public static operator T +(T x, T y) where T: IConvertible { var type = typeof(T); if (type == typeof(String) || type == typeof(DateTime)) throw new ArgumentException(String.Format("The type {0} is not supported", type.FullName), "T"); try { return (T)(Object)(x.ToDouble(NumberFormatInfo.CurrentInfo) + y.ToDouble(NumberFormatInfo.CurrentInfo)); } catch(Exception ex) { throw new ApplicationException("The operation failed.", ex); } } 

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

दुर्भाग्य से एक सामान्य पैरामीटर को एक अभिन्न प्रकार के रूप में बांटने का कोई तरीका नहीं है ( संपादित करें: मुझे लगता है कि "अंकगणितीय प्रकार" एक बेहतर शब्द हो सकता है क्योंकि यह केवल पूर्णांक से संबंधित नहीं है)।

ऐसा कुछ करने में सक्षम होना अच्छा होगा:

 where T : integral // or "arithmetical" depending on how pedantic you are 

या

 where T : IArithmetic 

मैं सुझाव दूँगा कि आप हमारे बहुत ही मार्कर ग्रेवेल और जॉन स्कीट द्वारा जेनेरिक ऑपरेटर पढ़ते हैं यह बताता है कि यह ऐसी मुश्किल समस्या क्यों है और इसके चारों ओर काम करने के लिए क्या किया जा सकता है।

.NET 2.0 ने जेनेटिक को एनएटी दुनिया में पेश किया, जिसने मौजूदा समस्याओं के कई सुरुचिपूर्ण समाधानों के लिए दरवाजा खोल दिया। सामान्य बाधाओं का इस्तेमाल टाइप-आर्ग्यूमेंट को ज्ञात इंटरफेसेस आदि को प्रतिबंधित करने के लिए किया जा सकता है, ताकि कार्यक्षमता तक पहुंच सुनिश्चित हो सके – या साधारण समानता / असमानता परीक्षण के लिए तुलनात्मक। डीफॉल्ट और इक्विटी कॉम्पैयरर। डीफॉल्ट सिंगलांस क्रमशः आईसीएमपीयर और आईक्यूवटी कॉम्पैपर क्रमशः लागू करता है ( उदाहरण के लिए, सवाल में "टी" के बारे में कुछ भी पता न हो)।

हालांकि, ऑपरेटरों की बातों के साथ, यह अभी भी एक बड़ा अंतर है। क्योंकि ऑपरेटर को स्थिर तरीके के रूप में घोषित किया जाता है, कोई इमाथ या समान समान इंटरफेस नहीं होता है, जो सभी संख्यात्मक प्रकार लागू होते हैं; और वास्तव में, ऑपरेटरों की लचीलेपन से यह एक सार्थक तरीके से करना कठिन होगा। इससे भी बदतर: आदिम प्रकार के कई ऑपरेटरों ऑपरेटरों के रूप में भी मौजूद नहीं हैं; बजाय प्रत्यक्ष आईएल तरीके हैं। [जोर देने] स्थिति को और भी जटिल बनाने के लिए, नल योग्य <> "उठाए गए ऑपरेटर" की अवधारणा की मांग करती है, जहां आंतरिक "टी" नल योग्य प्रकार पर लागू ऑपरेटरों का वर्णन करता है – लेकिन यह एक भाषा की सुविधा के रूप में लागू किया जाता है, और यह रनटाइम द्वारा प्रदान नहीं किया गया (प्रतिबिंब को और भी मजेदार बना दिया गया)

सी # 4.0 में आप इस सीमा को पाने के लिए गतिशील उपयोग कर सकते हैं। मैंने आपके कोड पर एक नज़र डाली, और एक काम (यद्यपि कटौती संस्करण) का निर्माण करने में कामयाब रहे:

  public class ConstrainedNumber<T> where T : struct, IComparable, IComparable<T>, IEquatable<T> { private T _value; public ConstrainedNumber(T value) { _value = value; } public static T operator +(ConstrainedNumber<T> x, ConstrainedNumber<T> y) { return (dynamic)x._value + y._value; } } 

और इसके साथ जाने के लिए एक छोटे से परीक्षण कार्यक्रम:

 class Program { static void Main(string[] args) { ConstrainedNumber<int> one = new ConstrainedNumber<int>(10); ConstrainedNumber<int> two = new ConstrainedNumber<int>(5); var three = one + two; Debug.Assert(three == 15); Console.ReadLine(); } } 

का आनंद लें!

नहीं, यह काम नहीं करता है लेकिन इस समस्या को हल करने के बारे में कुछ सुझाव हैं मैंने निम्नलिखित किया (शुद्ध पर विभिन्न स्रोतों से कुछ विचारों का प्रयोग करके):

 public delegate TResult BinaryOperator<TLeft, TRight, TResult>(TLeft left, TRight right); /// <summary> /// Provide efficient generic access to either native or static operators for the given type combination. /// </summary> /// <typeparam name="TLeft">The type of the left operand.</typeparam> /// <typeparam name="TRight">The type of the right operand.</typeparam> /// <typeparam name="TResult">The type of the result value.</typeparam> /// <remarks>Inspired by Keith Farmer's code on CodeProject:<br/>http://www.codeproject.com/KB/cs/genericoperators.aspx</remarks> public static class Operator<TLeft, TRight, TResult> { private static BinaryOperator<TLeft, TRight, TResult> addition; private static BinaryOperator<TLeft, TRight, TResult> bitwiseAnd; private static BinaryOperator<TLeft, TRight, TResult> bitwiseOr; private static BinaryOperator<TLeft, TRight, TResult> division; private static BinaryOperator<TLeft, TRight, TResult> exclusiveOr; private static BinaryOperator<TLeft, TRight, TResult> leftShift; private static BinaryOperator<TLeft, TRight, TResult> modulus; private static BinaryOperator<TLeft, TRight, TResult> multiply; private static BinaryOperator<TLeft, TRight, TResult> rightShift; private static BinaryOperator<TLeft, TRight, TResult> subtraction; /// <summary> /// Gets the addition operator + (either native or "op_Addition"). /// </summary> /// <value>The addition operator.</value> public static BinaryOperator<TLeft, TRight, TResult> Addition { get { if (addition == null) { addition = CreateOperator("op_Addition", OpCodes.Add); } return addition; } } /// <summary> /// Gets the modulus operator % (either native or "op_Modulus"). /// </summary> /// <value>The modulus operator.</value> public static BinaryOperator<TLeft, TRight, TResult> Modulus { get { if (modulus == null) { modulus = CreateOperator("op_Modulus", OpCodes.Rem); } return modulus; } } /// <summary> /// Gets the exclusive or operator ^ (either native or "op_ExclusiveOr"). /// </summary> /// <value>The exclusive or operator.</value> public static BinaryOperator<TLeft, TRight, TResult> ExclusiveOr { get { if (exclusiveOr == null) { exclusiveOr = CreateOperator("op_ExclusiveOr", OpCodes.Xor); } return exclusiveOr; } } /// <summary> /// Gets the bitwise and operator &amp; (either native or "op_BitwiseAnd"). /// </summary> /// <value>The bitwise and operator.</value> public static BinaryOperator<TLeft, TRight, TResult> BitwiseAnd { get { if (bitwiseAnd == null) { bitwiseAnd = CreateOperator("op_BitwiseAnd", OpCodes.And); } return bitwiseAnd; } } /// <summary> /// Gets the division operator / (either native or "op_Division"). /// </summary> /// <value>The division operator.</value> public static BinaryOperator<TLeft, TRight, TResult> Division { get { if (division == null) { division = CreateOperator("op_Division", OpCodes.Div); } return division; } } /// <summary> /// Gets the multiplication operator * (either native or "op_Multiply"). /// </summary> /// <value>The multiplication operator.</value> public static BinaryOperator<TLeft, TRight, TResult> Multiply { get { if (multiply == null) { multiply = CreateOperator("op_Multiply", OpCodes.Mul); } return multiply; } } /// <summary> /// Gets the bitwise or operator | (either native or "op_BitwiseOr"). /// </summary> /// <value>The bitwise or operator.</value> public static BinaryOperator<TLeft, TRight, TResult> BitwiseOr { get { if (bitwiseOr == null) { bitwiseOr = CreateOperator("op_BitwiseOr", OpCodes.Or); } return bitwiseOr; } } /// <summary> /// Gets the left shift operator &lt;&lt; (either native or "op_LeftShift"). /// </summary> /// <value>The left shift operator.</value> public static BinaryOperator<TLeft, TRight, TResult> LeftShift { get { if (leftShift == null) { leftShift = CreateOperator("op_LeftShift", OpCodes.Shl); } return leftShift; } } /// <summary> /// Gets the right shift operator &gt;&gt; (either native or "op_RightShift"). /// </summary> /// <value>The right shift operator.</value> public static BinaryOperator<TLeft, TRight, TResult> RightShift { get { if (rightShift == null) { rightShift = CreateOperator("op_RightShift", OpCodes.Shr); } return rightShift; } } /// <summary> /// Gets the subtraction operator - (either native or "op_Addition"). /// </summary> /// <value>The subtraction operator.</value> public static BinaryOperator<TLeft, TRight, TResult> Subtraction { get { if (subtraction == null) { subtraction = CreateOperator("op_Subtraction", OpCodes.Sub); } return subtraction; } } private static BinaryOperator<TLeft, TRight, TResult> CreateOperator(string operatorName, OpCode opCode) { if (operatorName == null) { throw new ArgumentNullException("operatorName"); } bool isPrimitive = true; bool isLeftNullable; bool isRightNullable = false; Type leftType = typeof(TLeft); Type rightType = typeof(TRight); MethodInfo operatorMethod = LookupOperatorMethod(ref leftType, operatorName, ref isPrimitive, out isLeftNullable) ?? LookupOperatorMethod(ref rightType, operatorName, ref isPrimitive, out isRightNullable); DynamicMethod method = new DynamicMethod(string.Format("{0}:{1}:{2}:{3}", operatorName, typeof(TLeft).FullName, typeof(TRight).FullName, typeof(TResult).FullName), typeof(TResult), new Type[] {typeof(TLeft), typeof(TRight)}); Debug.WriteLine(method.Name, "Generating operator method"); ILGenerator generator = method.GetILGenerator(); if (isPrimitive) { Debug.WriteLine("Primitives using opcode", "Emitting operator code"); generator.Emit(OpCodes.Ldarg_0); if (isLeftNullable) { generator.EmitCall(OpCodes.Call, typeof(TLeft).GetMethod("op_Explicit", BindingFlags.Public|BindingFlags.Static), null); } IlTypeHelper.ILType stackType = IlTypeHelper.EmitWidening(generator, IlTypeHelper.GetILType(leftType), IlTypeHelper.GetILType(rightType)); generator.Emit(OpCodes.Ldarg_1); if (isRightNullable) { generator.EmitCall(OpCodes.Call, typeof(TRight).GetMethod("op_Explicit", BindingFlags.Public | BindingFlags.Static), null); } stackType = IlTypeHelper.EmitWidening(generator, IlTypeHelper.GetILType(rightType), stackType); generator.Emit(opCode); if (typeof(TResult) == typeof(object)) { generator.Emit(OpCodes.Box, IlTypeHelper.GetPrimitiveType(stackType)); } else { Type resultType = typeof(TResult); if (IsNullable(ref resultType)) { generator.Emit(OpCodes.Newobj, typeof(TResult).GetConstructor(new Type[] {resultType})); } else { IlTypeHelper.EmitExplicit(generator, stackType, IlTypeHelper.GetILType(resultType)); } } } else if (operatorMethod != null) { Debug.WriteLine("Call to static operator method", "Emitting operator code"); generator.Emit(OpCodes.Ldarg_0); generator.Emit(OpCodes.Ldarg_1); generator.EmitCall(OpCodes.Call, operatorMethod, null); if (typeof(TResult).IsPrimitive && operatorMethod.ReturnType.IsPrimitive) { IlTypeHelper.EmitExplicit(generator, IlTypeHelper.GetILType(operatorMethod.ReturnType), IlTypeHelper.GetILType(typeof(TResult))); } else if (!typeof(TResult).IsAssignableFrom(operatorMethod.ReturnType)) { Debug.WriteLine("Conversion to return type", "Emitting operator code"); generator.Emit(OpCodes.Ldtoken, typeof(TResult)); generator.EmitCall(OpCodes.Call, typeof(Type).GetMethod("GetTypeFromHandle", new Type[] {typeof(RuntimeTypeHandle)}), null); generator.EmitCall(OpCodes.Call, typeof(Convert).GetMethod("ChangeType", new Type[] {typeof(object), typeof(Type)}), null); } } else { Debug.WriteLine("Throw NotSupportedException", "Emitting operator code"); generator.ThrowException(typeof(NotSupportedException)); } generator.Emit(OpCodes.Ret); return (BinaryOperator<TLeft, TRight, TResult>)method.CreateDelegate(typeof(BinaryOperator<TLeft, TRight, TResult>)); } private static bool IsNullable(ref Type type) { if (type.IsGenericType && (type.GetGenericTypeDefinition() == typeof(Nullable<>))) { type = type.GetGenericArguments()[0]; return true; } return false; } private static MethodInfo LookupOperatorMethod(ref Type type, string operatorName, ref bool isPrimitive, out bool isNullable) { isNullable = IsNullable(ref type); if (!type.IsPrimitive) { isPrimitive = false; foreach (MethodInfo methodInfo in type.GetMethods(BindingFlags.Static|BindingFlags.Public)) { if (methodInfo.Name == operatorName) { bool isMatch = true; foreach (ParameterInfo parameterInfo in methodInfo.GetParameters()) { switch (parameterInfo.Position) { case 0: if (parameterInfo.ParameterType != typeof(TLeft)) { isMatch = false; } break; case 1: if (parameterInfo.ParameterType != typeof(TRight)) { isMatch = false; } break; default: isMatch = false; break; } } if (isMatch) { if (typeof(TResult).IsAssignableFrom(methodInfo.ReturnType) || typeof(IConvertible).IsAssignableFrom(methodInfo.ReturnType)) { return methodInfo; // full signature match } } } } } return null; } } internal static class IlTypeHelper { [Flags] public enum ILType { None = 0, Unsigned = 1, B8 = 2, B16 = 4, B32 = 8, B64 = 16, Real = 32, I1 = B8, // 2 U1 = B8|Unsigned, // 3 I2 = B16, // 4 U2 = B16|Unsigned, // 5 I4 = B32, // 8 U4 = B32|Unsigned, // 9 I8 = B64, //16 U8 = B64|Unsigned, //17 R4 = B32|Real, //40 R8 = B64|Real //48 } public static ILType GetILType(Type type) { if (type == null) { throw new ArgumentNullException("type"); } if (!type.IsPrimitive) { throw new ArgumentException("IL native operations requires primitive types", "type"); } if (type == typeof(double)) { return ILType.R8; } if (type == typeof(float)) { return ILType.R4; } if (type == typeof(ulong)) { return ILType.U8; } if (type == typeof(long)) { return ILType.I8; } if (type == typeof(uint)) { return ILType.U4; } if (type == typeof(int)) { return ILType.I4; } if (type == typeof(short)) { return ILType.U2; } if (type == typeof(ushort)) { return ILType.I2; } if (type == typeof(byte)) { return ILType.U1; } if (type == typeof(sbyte)) { return ILType.I1; } return ILType.None; } public static Type GetPrimitiveType(ILType iLType) { switch (iLType) { case ILType.R8: return typeof(double); case ILType.R4: return typeof(float); case ILType.U8: return typeof(ulong); case ILType.I8: return typeof(long); case ILType.U4: return typeof(uint); case ILType.I4: return typeof(int); case ILType.U2: return typeof(short); case ILType.I2: return typeof(ushort); case ILType.U1: return typeof(byte); case ILType.I1: return typeof(sbyte); } throw new ArgumentOutOfRangeException("iLType"); } public static ILType EmitWidening(ILGenerator generator, ILType onStackIL, ILType otherIL) { if (generator == null) { throw new ArgumentNullException("generator"); } if (onStackIL == ILType.None) { throw new ArgumentException("Stack needs a value", "onStackIL"); } if (onStackIL < ILType.I8) { onStackIL = ILType.I8; } if ((onStackIL < otherIL) && (onStackIL != ILType.R4)) { switch (otherIL) { case ILType.R4: case ILType.R8: if ((onStackIL&ILType.Unsigned) == ILType.Unsigned) { generator.Emit(OpCodes.Conv_R_Un); } else if (onStackIL != ILType.R4) { generator.Emit(OpCodes.Conv_R8); } else { return ILType.R4; } return ILType.R8; case ILType.U8: case ILType.I8: if ((onStackIL&ILType.Unsigned) == ILType.Unsigned) { generator.Emit(OpCodes.Conv_U8); return ILType.U8; } if (onStackIL != ILType.I8) { generator.Emit(OpCodes.Conv_I8); } return ILType.I8; } } return onStackIL; } public static void EmitExplicit(ILGenerator generator, ILType onStackIL, ILType otherIL) { if (otherIL != onStackIL) { switch (otherIL) { case ILType.I1: generator.Emit(OpCodes.Conv_I1); break; case ILType.I2: generator.Emit(OpCodes.Conv_I2); break; case ILType.I4: generator.Emit(OpCodes.Conv_I4); break; case ILType.I8: generator.Emit(OpCodes.Conv_I8); break; case ILType.U1: generator.Emit(OpCodes.Conv_U1); break; case ILType.U2: generator.Emit(OpCodes.Conv_U2); break; case ILType.U4: generator.Emit(OpCodes.Conv_U4); break; case ILType.U8: generator.Emit(OpCodes.Conv_U8); break; case ILType.R4: generator.Emit(OpCodes.Conv_R4); break; case ILType.R8: generator.Emit(OpCodes.Conv_R8); break; } } } } 

इस तरह का प्रयोग करें: int i = ऑपरेटर.एस्डिशन (3, 5);

इसके लिए बाधाएं उपलब्ध नहीं हैं लेकिन इस समस्या को हल करने का एक तरीका है:

 public static T operator -(T foo, T bar) { return (T)System.Convert.ChangeType( System.Convert.ToDecimal(foo) - System.Convert.ToDecimal(bar), typeof(T)); } 

यदि आप अधिकतर प्रकारों का उपयोग नहीं कर रहे हैं, जिन्हें सामान्य तर्क के रूप में उपयोग किया जाता है और संकलन-समय जांच करना चाहते हैं, तो आप एक समाधान का उपयोग कर सकते हैं जो लुसेरो के समाधान के समान है।

आधार वर्ग

 public class Arithmetic<T> { protected static readonly Func<T, T, T> OP_ADD; protected static readonly Func<T, T, T> OP_MUL; protected static readonly Func<T, T, T> OP_SUB; /* Define all operators you need here */ static Arithmetic() { Arithmetic<Single>.OP_ADD = (x, y) => x + y; Arithmetic<Single>.OP_MUL = (x, y) => x * y; Arithmetic<Single>.OP_SUB = (x, y) => x - y; Arithmetic<Double>.OP_ADD = (x, y) => x + y; Arithmetic<Double>.OP_MUL = (x, y) => x * y; Arithmetic<Double>.OP_SUB = (x, y) => x - y; /* This could also be generated by a tool */ } } 

प्रयोग

 public class Vector2<T> : Arithmetic<T> { public TX; public TY; public static Vector2<T> operator +(Vector2<T> a, Vector2<T> b) { return new Vector2<T>() { X = OP_ADD(aX, bX), Y = OP_ADD(aY, bY) }; } public static Vector2<T> operator -(Vector2<T> a, Vector2<T> b) { return new Vector2<T>() { X = OP_SUB(aX, bX), Y = OP_SUB(aY, bY) }; } public static Vector2<T> operator *(Vector2<T> a, Vector2<T> b) { return new Vector2<T>() { X = OP_MUL(aX, bX), Y = OP_MUL(aY, bY) }; } } 

ऑपरेटर्स समर्थित हैं यह इंगित करने के लिए .Net generics में कोई वर्तमान समर्थन नहीं है।

यह बहुतायत से अनुरोधित सुविधा है।

यह अर्द्ध के आसपास काम किया जा सकता है (देखें MiscUtils ), लेकिन यह आपको सिंटैक्स आपको इच्छा नहीं देगा

मैंने यहां बस देखकर यह किया है। वेक्टर 4 <टी> वर्ग में सामान्य संख्या में सदिश गणित के साथ 4 प्रकार / अक्ष का प्रकार टी होता है। सिर्फ 2 इंस्ट्रूमेंट ऑप्स को डेसिमल में और कन्वर्ट करने के लिए जोड़ें। यह संभवतः संयुक्त राष्ट्र के रूप में है, जैसा आप प्राप्त करने जा रहे हैं, लेकिन जैसा कि आप बताते हैं, इससे अधिक सटीक और इस प्रकार भारी है जितना इसकी आवश्यकता है। आप लोगों की तरह, मैं चाहता हूं कि एक अनंतिम या कुछ और था!

public static Vector4<T> operator +(Vector4<T> a, Vector4<T> b) { Vector4<Decimal> A = a; Vector4<Decimal> B = b; var result = new Vector4<Decimal>(AX + BX, AY + BY, AZ + BZ, AW + BW); return result; } public static implicit operator Vector4<Decimal>(Vector4<T> v) { return new Vector4<Decimal>( Convert.ToDecimal(vX), Convert.ToDecimal(vY), Convert.ToDecimal(vZ), Convert.ToDecimal(vW)); } public static implicit operator Vector4<T>(Vector4<Decimal> v) { return new Vector4<T>( (T)Convert.ChangeType(vX, typeof(T)), (T)Convert.ChangeType(vY, typeof(T)), (T)Convert.ChangeType(vZ, typeof(T)), (T)Convert.ChangeType(vW, typeof(T))); }
public static Vector4<T> operator +(Vector4<T> a, Vector4<T> b) { Vector4<Decimal> A = a; Vector4<Decimal> B = b; var result = new Vector4<Decimal>(AX + BX, AY + BY, AZ + BZ, AW + BW); return result; } public static implicit operator Vector4<Decimal>(Vector4<T> v) { return new Vector4<Decimal>( Convert.ToDecimal(vX), Convert.ToDecimal(vY), Convert.ToDecimal(vZ), Convert.ToDecimal(vW)); } public static implicit operator Vector4<T>(Vector4<Decimal> v) { return new Vector4<T>( (T)Convert.ChangeType(vX, typeof(T)), (T)Convert.ChangeType(vY, typeof(T)), (T)Convert.ChangeType(vZ, typeof(T)), (T)Convert.ChangeType(vW, typeof(T))); } 

इस मित्र के बारे में (आरटीटीआई और ऑब्जेक्ट क्लास का उपयोग करके)

 class MyMath { public static T Add<T>(T a, T b) where T: struct { switch (typeof(T).Name) { case "Int32": return (T) (object)((int)(object)a + (int)(object)b); case "Double": return (T)(object)((double)(object)a + (double)(object)b); default: return default(T); } } } class Program { public static int Main() { Console.WriteLine(MyMath.Add<double>(3.6, 2.12)); return 0; } } 

दुर्भाग्य से, यह संभव नहीं है क्योंकि कोई IArithmetic नहीं है (जैसा कि आपने कहा था) IArithmetic को पूर्णांक के लिए परिभाषित किया गया है। आप उन आदिम प्रकारों को ऐसे वर्गों में लपेट सकते हैं जो इस तरह के इंटरफ़ेस को कार्यान्वित करते हैं।

मैंने अभिव्यक्ति के पेड़ों से जुड़े कुछ संभावित समाधान देखे हैं, जहां ऑपरेटर अभिव्यक्ति मैन्युअल रूप से बनाई जाती है।

यह सही नहीं है क्योंकि आप संकलन-समय सत्यापन खो देते हैं, लेकिन यह आपके लिए चाल हो सकती है।

यहाँ के बारे में एक लेख है

अगर मुझे ऐसा कुछ करना था, तो मैं शायद इसे की तरफ खींचूँगा

 public class ConstrainedNumber<T> { private T Value { get; } public ConstrainedNumber(T value) { Value = value; } private static Func<ConstrainedNumber<T>, ConstrainedNumber<T>, T> _addFunc; // Cache the delegate public static ConstrainedNumber<T> operator+(ConstrainedNumber<T> left, ConstrainedNumber<T> right) { var adder = _addFunc; if (adder == null) { ParameterExpression lhs = Expression.Parameter(typeof(ConstrainedNumber<T>)); ParameterExpression rhs = Expression.Parameter(typeof(ConstrainedNumber<T>)); _addFunc = adder = Expression.Lambda<Func<ConstrainedNumber<T>, ConstrainedNumber<T>, T>>( Expression.Add( Expression.Property(lhs, nameof(Value)), Expression.Property(lhs, nameof(Value)) ), lhs, rhs).Compile(); } return new ConstrainedNumber<T>(adder(left, right)); } } 

अंतिम परिणाम dynamic दृष्टिकोण के अंतिम परिणाम की तरह थोड़ा सा है, जो वास्तव में आंतरिक रूप से इस तरह से कुछ करना चाहिए, लेकिन थोड़ी अधिक ऊपरी हिस्से के साथ, और किसी भी T लिए काम करना चाहिए जो कि या तो एक अंकगणित आदिम या + ऑपरेटर है इसके लिए परिभाषित एक ऐसा मामला जो dynamic दृष्टिकोण अलग तरीके से संभालता है यह है कि यह string लिए काम करेगा जबकि यह नहीं होगा। चाहे वह एक अच्छा या बुरी बात है, उपयोग के मामले पर निर्भर करता है, लेकिन अगर इसकी आवश्यकता होती है तो string विशेष-स्थित हो सकती है।