2012-07-03 22 views
60

मेरे पास एक सामान्य विधि है जो एक अनुरोध लेती है और एक प्रतिक्रिया प्रदान करती है।सी # जेनेरिक में शून्य?

public Tres DoSomething<Tres, Treq>(Tres response, Treq request) 
{/*stuff*/} 

लेकिन मैं हमेशा अपने अनुरोध के लिए प्रतिक्रिया नहीं चाहता हूं, और मैं हमेशा प्रतिक्रिया प्राप्त करने के लिए अनुरोध डेटा नहीं चाहता हूं। मैं मामूली परिवर्तन करने के लिए पूरी तरह से विधियों की प्रतिलिपि बनाना और पेस्ट नहीं करना चाहता हूं। मैं जो चाहता हूं, वह ऐसा करने में सक्षम होना है:

public Tre DoSomething<Tres>(Tres response) 
{ 
    return DoSomething<Tres, void>(response, null); 
} 

क्या यह किसी भी तरह से व्यवहार्य है? ऐसा लगता है कि विशेष रूप से शून्य का उपयोग करना काम नहीं करता है, लेकिन मैं कुछ समान खोजने की उम्मीद कर रहा हूं।

+1

क्यों न केवल System.Object का उपयोग करें और DoSomething (Tres प्रतिक्रिया, ट्रेक अनुरोध) में एक शून्य जांच करें? – James

+0

ध्यान दें कि आपको वापसी मूल्य का उपयोग करने की आवश्यकता है। आप प्रक्रियाओं जैसे कार्यों को कॉल कर सकते हैं। 'कुछ = (x); 'y = doSomething (x);' –

उत्तर

61

आप void उपयोग कर सकते हैं नहीं है, लेकिन आप object उपयोग कर सकते हैं: क्योंकि आपका होगा-मानना ​​void कार्यों null वापस जाने के लिए की जरूरत है यह एक छोटे असुविधा है, लेकिन अगर यह आपके कोड को एकीकृत, यह एक छोटे से कीमत अदा करने को होना चाहिए।

यह void उपयोग करने के लिए के रूप में एक वापसी प्रकार कम से कम आंशिक सामान्य प्रतिनिधियों की Func<...> और Action<...> परिवारों के बीच एक विभाजन के लिए जिम्मेदार है असमर्थता: यह संभव हो गया void वापस जाने के लिए सभी Action<X,Y,Z> बस Func<X,Y,Z,void> बन जाएगा था। दुर्भाग्य से, यह संभव नहीं है।

+26

** (मजाक) ** के बजाय 'और वह अभी भी उन वापसी विधियों से' शून्य 'वापस कर सकता है,' रिटर्न सिस्टम 'के साथ। रनटाइम। Serialization.FormatterServices.GetUninitializedObject (typeof (शून्य)); '। हालांकि, यह एक बॉक्सिंग शून्य होगा। –

1

void, हालांकि एक प्रकार, केवल एक विधि के रिटर्न प्रकार के रूप में मान्य है।

void की इस सीमा के आसपास कोई रास्ता नहीं है।

61

नहीं, दुर्भाग्य से नहीं। यदि void एक "असली" प्रकार था (उदाहरण के लिए unit in F#, उदाहरण के लिए) जीवन कई तरीकों से बहुत आसान होगा। विशेष रूप से, हम दोनों Func<T> और Action<T> परिवारों ज़रूरत नहीं होगी - बस होगी Func<void> बजाय Action, Func<T, void> बजाय Action<T> आदि

यह भी async बनाना होगा आसान - वहाँ की कोई आवश्यकता नहीं होगी गैर-जेनेरिक Task बिल्कुल टाइप करें - हमारे पास Task<void> होगा।

दुर्भाग्य से, कि जिस तरह से सी # या .NET प्रकार सिस्टम काम ...

+4

दुर्भाग्यवश, सी # या .NET प्रकार सिस्टम काम करने का तरीका नहीं है ... 'आप मुझे उम्मीद कर रहे थे कि शायद चीजें इस तरह काम कर सकती हैं। क्या आपका आखिरी बिंदु यह है कि हमारे पास ऐसी चीजें काम करने की संभावना नहीं है? –

+2

@ सahuगिन: मुझे संदेह नहीं है - यह इस बिंदु पर एक बहुत बड़ा बदलाव होगा। –

+0

एक प्रकार के रूप में शून्य को अनुमति देना एक संदर्भ के रूप में शून्य की अनुमति देने जैसा होगा? एक और अरब डॉलर की गलती? – stannius

13

आप बस Object इस्तेमाल कर सकते हैं के रूप में दूसरों का सुझाव दिया है नहीं है। या Int32 जो मैंने कुछ उपयोग देखा है। Int32 का उपयोग करके "डमी" संख्या का उपयोग करें (0 का उपयोग करें), लेकिन कम से कम आप Int32 संदर्भ (structs मुहरबंद) में कोई बड़ी और विदेशी वस्तु नहीं डाल सकते हैं।

तुम भी आप के मालिक हैं "शून्य" प्रकार लिख सकते हैं:

public sealed class MyVoid 
{ 
    MyVoid() 
    { 
    throw new InvalidOperationException("Don't instantiate MyVoid."); 
    } 
} 

MyVoid संदर्भों की अनुमति दी है (यह एक स्थिर वर्ग नहीं है), लेकिन केवल null हो सकता है। इंस्टेंस कन्स्ट्रक्टर निजी है (और अगर कोई इस निजी कन्स्ट्रक्टर को प्रतिबिंब के माध्यम से कॉल करने का प्रयास करता है, तो उन पर एक अपवाद फेंक दिया जाएगा)।

+2

इसके लिए एक और नाम शून्य ऑब्जेक्ट पैटर्न (डिज़ाइन पैटर्न) होगा। – Aelphaeis

18

यहां आप क्या कर सकते हैं। जैसा कि जॉन जॉकेट ने कहा कि सी # में कोई इकाई प्रकार नहीं है, इसलिए इसे स्वयं बनाएं!

public sealed class ThankYou { 
    private ThankYou() { } 
    private readonly static ThankYou bye = new ThankYou(); 
    public static ThankYou Bye { get { return bye; } } 
} 

अब आप हमेशा Action<...>

public ThankYou MethodWithNoResult() { 
    /* do things */ 
    return ThankYou.Bye; 
} 

के बजाय Func<..., ThankYou> का उपयोग या कुछ पहले से ही आरएक्स टीम द्वारा की गई उपयोग कर सकते हैं: http://msdn.microsoft.com/en-us/library/system.reactive.unit%28v=VS.103%29.aspx

+0

सिस्टम। प्रतिक्रियाशील। एक अच्छा सुझाव है। नवंबर 2016 तक, यदि आप यथासंभव प्रतिक्रियाशील ढांचे के टुकड़े को छोटा करने में रुचि रखते हैं, क्योंकि आप यूनिट क्लास के अलावा किसी अन्य चीज का उपयोग नहीं कर रहे हैं, तो nuget पैकेज मैनेजर 'इंस्टाल-पैकेज सिस्टम का उपयोग करें। प्रतिक्रियाशील। कोर' – DannyMeister

1

मैं ऊपर अलेक्सी Bykov द्वारा विचार पसंद है, लेकिन यह कर सकता है थोड़ा सा

public sealed class Nothing { 
    public static Nothing AtAll { get { return null; } } 
} 

जैसा कि मैंने सरल बनाया कोई स्पष्ट कारण नहीं है क्यों कुछ भी नहीं। सभी केवल शून्य

एक ही विचार (या जेप स्टेग नील्सन द्वारा एक) टाइप किए गए वर्गों के उपयोग के लिए भी बहुत अच्छा है।

उदा। यदि प्रकार का उपयोग केवल कुछ विधि के लिए तर्क के रूप में पारित प्रक्रिया/फ़ंक्शन के तर्कों का वर्णन करने के लिए किया जाता है, और यह स्वयं कोई तर्क नहीं लेता है।

(आप अभी भी या तो एक डमी आवरण बनाने के लिए या एक वैकल्पिक "कुछ भी नहीं" अनुमति देने के लिए की आवश्यकता होगी। लेकिन IMHO वर्ग उपयोग myClass < कुछ भी नहीं है> साथ अच्छा लग रहा है)

void myProcWithNoArguments(Nothing Dummy){ 
    myProcWithNoArguments(){ 
} 

या

void myProcWithNoArguments(Nothing Dummy=null){ 
    ... 
} 
+0

मूल्य 'शून्य' में अनुपलब्ध या अनुपस्थित 'ऑब्जेक्ट 'होने का अर्थ है। 'कुछ भी नहीं' के लिए केवल एक मान होने का मतलब है कि यह कभी और कुछ नहीं दिखता है। – LexieHankins

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