2009-08-11 18 views
20

क्या सी # में एक विस्तार विधि बनाना वास्तव में असंभव है जहां उदाहरण संदर्भ के रूप में पारित किया गया है?सी # एक्सटेंशन तरीके संदर्भ द्वारा पैरामीटर पास करने की अनुमति नहीं देता है?

Imports System.Runtime.CompilerServices 

Module Module1 
    Sub Main() 
    Dim workDays As Weekdays 

    workDays.Add(Weekdays.Monday) 
    workDays.Add(Weekdays.Tuesday) 

    Console.WriteLine("Tuesday is a workday: {0}", _ 
     CBool(workDays And Weekdays.Tuesday)) 
    Console.ReadKey() 
    End Sub 
End Module 

<Flags()> _ 
Public Enum Weekdays 
    Monday = 1 
    Tuesday = 2 
    Wednesday = 4 
    Thursday = 8 
    Friday = 16 
    Saturday = 32 
    Sunday = 64 
End Enum 

Module Ext 
    <Extension()> _ 
    Public Sub Add(ByRef Value As Weekdays, ByVal Arg1 As Weekdays) 
    Value = Value + Arg1 
    End Sub 
End Module 

नोट मूल्य पैरामीटर ByRef पारित हो जाता है:

यहां नमूने VB.NET सांत्वना अनुप्रयोग है।

और (लगभग) सी # में एक ही:

using System; 

namespace CS.Temp 
{ 
    class Program 
    { 
    public static void Main() 
    { 
     Weekdays workDays = 0; 

     workDays.Add(Weekdays.Monday); // This won't work 
     workDays.Add(Weekdays.Tuesday); 

     // You have to use this syntax instead... 
     // workDays = workDays | Weekdays.Monday; 
     // workDays = workDays | Weekdays.Tuesday; 

     Console.WriteLine("Tuesday is a workday: {0}", _ 
     System.Convert.ToBoolean(workDays & Weekdays.Tuesday)); 
     Console.ReadKey(); 
    } 
    } 

    [Flags()] 
    public enum Weekdays : int 
    { 
    Monday = 1, 
    Tuesday = 2, 
    Wednesday = 4, 
    Thursday = 8, 
    Friday = 16, 
    Saturday = 32, 
    Sunday = 64 
    } 

    public static class Ext 
    { 
    // Value cannot be passed by reference? 
    public static void Add(this Weekdays Value, Weekdays Arg1) 
    { 
     Value = Value | Arg1; 
    } 
    } 
} 

Add विस्तार विधि सी # में काम नहीं करता क्योंकि मैं ref कीवर्ड का उपयोग नहीं कर सकते। क्या इसके समाधान की कोई युक्ति है?

+0

बस पूरा होने की खातिर: सही तरीका करने के लिए एक झंडा enum के एक मूल्य "जोड़ें" 'मान = मूल्य या Arg1' जब तक आप चाहते हैं कि जोड़ने' Monday' दो बार 'Tuesday' जोड़ने की तरह बर्ताव करता है। ध्वज को हटाने का सही तरीका 'Value = (Value या Arg1) Xor Arg1' है। – LWChris

उत्तर

12

नंबर सी # में, आप नहीं किसी भी संशोधक एक विस्तार विधि के पहले पैरामीटर के लिए अन्य this से ('बाहर' या ref की तरह) निर्दिष्ट कर सकते हैं। वीबी सिंटेक्स से परिचित नहीं है लेकिन ऐसा लगता है कि एक विस्तार विधि को चिह्नित करने के लिए एक घोषणात्मक दृष्टिकोण का उपयोग करना प्रतीत होता है।

जब आप इसे कहते हैं, तो आप पहले this पैरामीटर निर्दिष्ट नहीं । इसलिए के रूप में बाहर पैरामीटर अंकन या रेफरी does not को समझ बनाने के रूप में आप जब आप इसे कॉल की तरह आप सामान्य तरीके

void MyInstanceMethod(ref SomeClass c, int data) { ... } // definition 

obj.MyInstanceMethod(ref someClassObj, 10);    // call 

void MyExtensionMethod(this SomeClass c, int data) {.... } // defn 

c.MyExtensionMethod(10);         // call 

मुझे लगता है कि मुसीबत तुम यहाँ आ रही हैं, से संबंधित है में करते हैं, संशोधक निर्दिष्ट नहीं कर सकते मूल्य प्रकार अपरिवर्तनीय है। यदि सप्ताहांत एक संदर्भ प्रकार था, तो यह ठीक से काम करेगा। अपरिवर्तनीय प्रकारों (structs) के लिए, defacto तरीका आवश्यक मान के साथ एक नया उदाहरण वापस करने के लिए है। जैसे संरचना दिनांक समय पर जोड़ें विधि देखें, यह एक नया डेटटाइम उदाहरण देता है जिसका मूल्य = रिसीवर दिनांक समय उदाहरण का मान + param मान।

public DateTime Add(TimeSpan value) 
+0

vb में, कोई निर्दिष्ट कर सकता है कि एक एक्सटेंशन विधि ''' '' '''' को' ByRef' पैरामीटर के रूप में निहित करती है; दुर्भाग्य से, संकलक तब पढ़ने के लिए केवल संरचनाओं को पारित करने की अनुमति देता है। परिवर्तनीय मूल्य प्रकारों के बारे में प्रमुख शिकायतों में से एक यह है कि इस बात को इंगित करने के लिए कुछ भी नहीं है कि कौन सी विधियां 'इस' को बदलती हैं, वे इस तरह के तरीकों को केवल पढ़ने के उदाहरणों पर बेकार कहने की अनुमति देते हैं। मुझे यह अजीब लगता है कि vb.net कार्यान्वयनकर्ता एक विस्तार विधि को अनुमति देने का निर्णय लेगा जो 'ByRef' पैरामीटर लेता है - व्यावहारिक रूप से चिल्लाना" मैं तर्क को म्यूट कर दूंगा! "- केवल पढ़ने के संदर्भ में। – supercat

11

यिक्स - आप एक परिवर्तनीय अपरिवर्तनीय संरचना बना रहे हैं। यह टूट जाता है लोग सी # में देखने के लिए क्या उम्मीद है, लेकिन अगर आप चाहिए, तो आप हमेशा सीधे विधि कॉल कर सकते हैं:

Ext.Add(ref value, arg1); 

कोई भी एक्सटेंशन विधि सीधे प्रतिदेय है।

इसके अलावा

, एक स्पष्टीकरण:

SomeReferenceType value = ...; 
SomeReferenceType copy = value; 
value.ExtensionMethodByRef(...); 
// this failing is semantically ridiculous for reference types, which 
// is why it makes no sense to pass a `this` parameter by ref. 
object.ReferenceEquals(value, copy); 
+4

उत्परिवर्तनीय अपरिवर्तनीय संरचना? –

+1

हां, एरिक लिपर्ट इसे पसंद करेंगे;) –

+2

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

4

अजीब VB.NET इस की अनुमति देता है और सी # नहीं है कि ...

हालांकि, हालांकि यह देखने की एक तकनीकी बिंदु से कोई मतलब हो सकता है (के बाद से एक विस्तार विधि केवल एक स्थैतिक विधि है), मुझे लगता है कि यह सही नहीं लगता है, क्योंकि विस्तार विधियों का उपयोग किया जाता है जैसे कि वे उदाहरण विधियां थे, और उदाहरण विधियां this संदर्भ को संशोधित नहीं कर सकती हैं। आप कर सकते हैं दूसरों के लिए -

+8

वास्तव में उदाहरण विधियों * * मूल्य प्रकार में "यह" संशोधित कर सकते हैं। अजीब लेकिन सच है। –

+1

वाह ... मैंने कभी यह महसूस नहीं किया! –

+3

यह कहने की जरूरत नहीं है कि यह SUCKS सी # के लिए बड़ा समय है। –

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

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