2012-02-18 11 views
5

संभव डुप्लिकेट:
C# generic constraint for only integersसी # में सामान्य संख्या कैसे योग करें?

आप निम्नलिखित कोड में देख सकते हैं, मैं दो सामान्य संख्याओं का योग की गणना करने की जरूरत है।

ऑपरेटर '+' प्रकार के ऑपरेंड के लिए लागू नहीं किया जा सकता:

public class NumberContainer<T> 
{ 
    public T ValueA { get; private set; } 
    public T ValueB { get; private set; } 
    public T Total { get { return ValueA + ValueB; } } 
} 

हालांकि, यह जो नीचे संकलक त्रुटि में परिणाम है दो टी मूल्यों का एक सीधा इसके अलावा, ऐसा करने के लिए संभव नहीं है 'टी' और 'टी'

यह देखते हुए कि मुझे लगता है मैं कैसा प्रदर्शन कर सकते से मूल्य प्रकार दिए गए नंबर (छोटा है, ushort, पूर्णांक, uint, आदि) का प्रतिनिधित्व करते हैं और कुछ के लिए T उपयोग करने का इरादा नहीं है, योग?

+0

या संभवतः के लिए कार्यान्वयन प्रदान की प्राप्त हो सकते हैं: [वहाँ "वास्तविक संख्या" के लिए एक सी # सामान्य बाधा है प्रकार?] (http://stackoverflow.com/questions/1348594/is-there-ac-sharp-generic-constraint-for-real-number-types/1348625#1348625) –

+1

प्रश्न प्रश्नों के डुप्लिकेट के रूप में बंद है 'टी' पर बाधा डालने की मांग, जो * यह नहीं है कि यह प्रश्न क्या करने का प्रयास कर रहा है। मुझे लगता है कि इसे फिर से खोलना चाहिए। – dasblinkenlight

उत्तर

12

आप "थोड़ा जादू" LINQ से साथ यह कर सकते हैं:

private static readonly Func<T, T, T> adder; 
static NumberContainer() { 
    var p1 = Expression.Parameter(typeof (T)); 
    var p2 = Expression.Parameter(typeof (T)); 
    adder = (Func<T, T, T>)Expression 
     .Lambda(Expression.Add(p1, p2), p1, p2) 
     .Compile(); 
} 
public T Total { get { return adder(ValueA, ValueB); } } 

केवल दोष यह है कि इस कोड संकलन जाएगा, भले ही NumberContainer एक प्रकार T कि इसके समर्थन नहीं करता है के साथ instantiated है; बेशक यह रन-टाइम पर अपवाद फेंक देगा। एक अतिरिक्त लाभ यह है कि यह उपयोगकर्ता-परिभाषित + ऑपरेटरों के साथ काम करना चाहिए।

1

आप T के लिए एक बाधा निर्दिष्ट कर सकते हैं कि यह एक struct होना चाहिए, और शायद यह है कि यह IConvertable लागू करता है, और फिर Convert का उपयोग करें (दक्षता एक पहलू पर विचार किया जाना है)।

public class NumberContainer<T> 
     where T : struct, IConvertible 
    { 
     public T ValueA { get; private set; } 
     public T ValueB { get; private set; } 
     public T Total { 
      get 
      { 
       // do type checking here, then: 

       return (T)Convert.ChangeType(
        Convert.ToDouble((object)ValueA) + 
        Convert.ToDouble((object)ValueB), typeof(T)); 
      } 
     } 
    } 

हालांकि, जेनिक्स के साथ यह गारंटी देने का कोई तरीका नहीं है कि टी संकलन समय पर एक पूर्णांक या फ़्लोटिंग प्रकार है। आप इसे रनटाइम पर देख सकते हैं, हालांकि, और अपवाद फेंक सकते हैं।

+0

यह या तो काम नहीं करेगा। वास्तव में आपका सुझाव संकलन भी नहीं करता है। –

+0

क्या यह मेरे सिर, फिक्स्ड और कंपाइल के शीर्ष से बाहर था। यदि आप आगे विस्तार करना चाहते हैं कि यह क्यों काम नहीं करेगा, तो यह बहुत उपयोगी होगा। – HackedByChinese

+0

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

5

LINQ, उपयोग करने के अलावा अगर आप dynamic का उपयोग कर .NET 4 यह संभव है पर कर रहे हैं:

static T Add<T>(T x, T y) 
{ 
    dynamic dx = x, dy = y; 
    return dx + dy; 
} 

अपने कोड नमूने में यह बदल जाता है में:

public class NumberContainer<T> where T: struct 
{ 
    public T ValueA { get; private set; } 
    public T ValueB { get; private set; } 
    public T Total { get { return ((dynamic)ValueA) + ((dynamic)ValueB); } } 
} 

यह दृष्टिकोण 'नहीं करता है हालांकि सुरक्षा सुनिश्चित करें। यदि T कुछ यादृच्छिक संरचना है जो + का समर्थन नहीं करती है तो आप एक अपवाद (मुझे लगता है) के साथ समाप्त हो जाएगा।

+0

गतिशील का डरावना उपयोग, विशेष रूप से ऑपरेटरों पर विचार करना वर्चुअल नहीं है ... मुझे लगता है कि यह इसके जादू बॉक्स द्वारा "बस काम करेगा"। (मैं संरचनात्मक प्रकारों को भी पसंद करता हूं * * - /) –

+0

@pst - सहमत है, लेकिन यह काम करने के लिए होता है। हालांकि मैं इस बिंदु को समझता हूं। –

1

तुम बस एक सार आधार वर्ग के रूप में इस का इलाज और विशिष्ट वर्गों है कि टी मूल्य निर्दिष्ट और कुल

public abstract class NumberContainer<T> 
    where T: struct 
{ 
    public T ValueA { get; private set; } 
    public T ValueB { get; private set; } 
    public abstract T Total(); 
} 

public class IntContainer : NumberContainer<int> 
{ 
    public override int Total() 
    { 
     return ValueA + ValueB; 
    } 
} 
+1

यदि 'int' को 'टी' में परिवर्तित किया जा सकता है तो यह कोई समस्या नहीं होगी। आपका कोड संकलित नहीं करता है। –

+0

मुझे मूर्खतापूर्ण। एक वैकल्पिक समाधान प्रदान करने के लिए अद्यतन उत्तर क्योंकि अब गतिशीलता और लिंक का उपयोग कर कुछ समाधान हैं –

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