ऑपरेटर # C एक्सटेंशन एक्सटेंशन के साथ ओवरलोडिंग


174

मैं C # StringBuilderवर्ग के लिए एक ऑपरेटर अधिभार जोड़ने के लिए विस्तार विधियों का उपयोग करने का प्रयास कर रहा हूं । विशेष रूप से, दिया गया StringBuilder sb, मैं इसके sb += "text"समकक्ष बनना चाहता हूं sb.Append("text")

यहाँ के लिए एक विस्तार विधि बनाने के लिए वाक्यविन्यास है StringBuilder:

public static class sbExtensions
{
    public static StringBuilder blah(this StringBuilder sb)
    {
        return sb;
    }
} 

यह सफलतापूर्वक blahएक्सटेंशन विधि को जोड़ता है StringBuilder

दुर्भाग्य से, ऑपरेटर ओवरलोडिंग काम नहीं करता है:

public static class sbExtensions
{
    public static StringBuilder operator +(this StringBuilder sb, string s)
    {
        return sb.Append(s);
    }
} 

अन्य मुद्दों के बीच, thisइस संदर्भ में कीवर्ड की अनुमति नहीं है।

क्या संचालक अधिभार को विस्तार विधियों से जोड़ना संभव है? यदि हां, तो इसके बारे में जाने का उचित तरीका क्या है?


4
हालांकि यह पहली बार एक शांत विचार की तरह लगता है, var otherSb = sb + "hi" पर विचार करें;
हैचेट -

जवाबों:


150

वर्तमान में यह संभव नहीं है, क्योंकि विस्तार विधियां स्थिर कक्षाओं में होनी चाहिए, और स्थैतिक कक्षाओं में ऑपरेटर अधिभार नहीं हो सकते हैं।

Mads Torgersen, C # Language PM कहते हैं:

... ओरकास रिलीज के लिए हमने सतर्क दृष्टिकोण अपनाने और केवल नियमित विस्तार विधियों को जोड़ने का फैसला किया, क्योंकि प्रेषण गुणों, घटनाओं, ऑपरेटरों, स्थिर तरीकों, आदि के विपरीत। नियमित विस्तार के तरीके वे थे जो हमें LINQ के लिए आवश्यक थे, और वे थे एक वाक्यात्मक न्यूनतम डिजाइन जो आसानी से अन्य सदस्य प्रकारों में से कुछ के लिए नकल नहीं किया जा सकता है।

हम तेजी से जानते हैं कि अन्य प्रकार के विस्तार सदस्य उपयोगी हो सकते हैं, और इसलिए हम ओरकास के बाद इस मुद्दे पर लौटेंगे। हालांकि, कोई गारंटी नहीं!

संपादित करें:

मैंने अभी देखा, मैड्स ने एक ही लेख में अधिक लिखा :

मुझे यह बताते हुए खेद है कि हम अगली रिलीज में ऐसा नहीं करेंगे। हमने अपनी योजनाओं में विस्तार के सदस्यों को बहुत गंभीरता से लिया, और उन्हें ठीक करने के लिए बहुत प्रयास किए, लेकिन अंत में हम इसे आसानी से प्राप्त नहीं कर सके, और अन्य दिलचस्प विशेषताओं को रास्ता देने का फैसला किया।

यह अभी भी भविष्य के रिलीज के लिए हमारे रडार पर है। यदि हमें सम्मोहक परिदृश्यों की एक अच्छी मात्रा मिलती है जो सही डिज़ाइन को चलाने में मदद कर सकते हैं तो क्या होगा।


यह सुविधा वर्तमान में C # 8.0 के लिए तालिका (संभावित) पर है। मैड्स इसे यहां लागू करने के बारे में कुछ और बात करते हैं


यह पेज तब से लिया गया है; यह समस्या अभी भी हल नहीं हुई है।
क्रिस मोसिनकी

17
बहुत बुरा। मैं सिर्फ एक ऑपरेटर को स्केलर मान द्वारा टाइमस्पैन को गुणा करने के लिए जोड़ना चाहता था ... :(
फिलिप स्कैकुन

मैं Stringएक PowerShell को कास्ट करने के लिए इसी अवधारणा को लागू करने की उम्मीद कर रहा था ScriptBlock
ट्रेवर सुलिवन

इसका मतलब है कि मैं xor betwen बूलियंस होने के लिए% को अधिभार नहीं दे सकता हूं? :( पर मृत true.Xor(false)तो
चिंगारी

3
@SparK ^C # में जैक ऑपरेटर है
जैकब

57

यदि आप उन स्थानों को नियंत्रित करते हैं, जहाँ आप इस "एक्सटेंशन ऑपरेटर" का उपयोग करना चाहते हैं (जो आप सामान्य रूप से वैसे भी एक्सटेंशन विधियों के साथ करते हैं), तो आप इस तरह से कर सकते हैं:

class Program {

  static void Main(string[] args) {
    StringBuilder sb = new StringBuilder();
    ReceiveImportantMessage(sb);
    Console.WriteLine(sb.ToString());
  }

  // the important thing is to use StringBuilderWrapper!
  private static void ReceiveImportantMessage(StringBuilderWrapper sb) {
    sb += "Hello World!";
  }

}

public class StringBuilderWrapper {

  public StringBuilderWrapper(StringBuilder sb) { StringBuilder = sb; }
  public StringBuilder StringBuilder { get; private set; }

  public static implicit operator StringBuilderWrapper(StringBuilder sb) {
    return new StringBuilderWrapper(sb);
  }

  public static StringBuilderWrapper operator +(StringBuilderWrapper sbw, string s) { 
      sbw.StringBuilder.Append(s);
      return sbw;
  }

} 

StringBuilderWrapperवर्ग एक वाणी अंतर्निहित रूपांतरण ऑपरेटर एक से StringBuilder और वांछित वाणी +ऑपरेटर। इस तरह, एक StringBuilderको पारित किया जा सकता है ReceiveImportantMessage, जिसे चुपचाप एक में बदल दिया जाएगा StringBuilderWrapper, जहां +ऑपरेटर का उपयोग किया जा सकता है।

इस तथ्य को कॉल करने वालों के लिए और अधिक पारदर्शी बनाने के लिए, आप इस तरह से ReceiveImportantMessageएक StringBuilderऔर बस कोड का उपयोग करने की घोषणा कर सकते हैं :

  private static void ReceiveImportantMessage(StringBuilder sb) {
    StringBuilderWrapper sbw = sb;
    sbw += "Hello World!";
  }

या, यह इनलाइन उपयोग करने के लिए जहां आप पहले से ही उपयोग कर रहे हैं StringBuilder, आप बस यह कर सकते हैं:

 StringBuilder sb = new StringBuilder();
 StringBuilderWrapper sbw = sb;
 sbw += "Hello World!";
 Console.WriteLine(sb.ToString());

मैंने और अधिक समझने के लिए एक समान दृष्टिकोण का उपयोग करने के बारे में एक पोस्ट बनाया IComparable


2
@ लियोन: मैं वास्तव में इसे बनाने के लिए था, इससे विरासत में नहीं मिला। वैसे भी, मैं इसे से विरासत में नहीं मिला क्योंकि यह सील है।
जोर्डो

5
@ लीलोन: यही इस तकनीक का दिल है। मैं ऐसा कर सकता हूं क्योंकि इसमें एक अंतर्निहित रूपांतरण ऑपरेटर घोषित किया गया StringBuilderWrapperहै जो इसे संभव बनाता है।
जोर्डो

1
@ पाब्लोवर: आप सही कह रहे हैं, इसके लिए एक नया प्रकार बनाने की आवश्यकता होती है, जो टाइप को लपेट देगा StringBuilderऔर इससे एक अंतर्निहित रूपांतरण ऑपरेटर प्रदान करेगा। उसके बाद, इसे स्ट्रिंग शाब्दिक के साथ इस्तेमाल किया जा सकता है, जैसा कि उदाहरण में प्रदर्शित किया गया है:sb += "Hello World!";
जोर्डो

2
क्या मैं सुझाव दे सकता हूं String: एक विस्तार विधि को इसमें जोड़ने के लिए : PushIndent(" ".X(4))(यह भी कहा जा सकता है Times)। या शायद इस निर्माणकर्ता का उपयोग कर रहे हैं PushIndent(new String(' ', 4)):।
जोर्डो

1
@ जोर्डो: शानदार जवाब;)
विंची

8

ऐसा प्रतीत होता है कि यह वर्तमान में संभव नहीं है - Microsoft कनेक्ट पर इस बहुत सुविधा का अनुरोध करने वाला एक खुला फीडबैक मुद्दा है:

http://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=168224

यह सुझाव देते हुए कि यह भविष्य में रिलीज़ हो सकता है लेकिन वर्तमान संस्करण के लिए लागू नहीं किया गया है।


आप वास्तव में क्या मतलब है, "वर्तमान में संभव नहीं है?" यह CLR में संभव होना चाहिए क्योंकि F # सब कुछ एक्सटेंशन का समर्थन करता है।
मैथ्यू ओलेनिक

1
मुझे लगता है कि उसका मतलब है कि यह C # में संभव नहीं है, CLR नहीं। पूरे विस्तार के तरीके की बात वैसे भी C # कंपाइलर ट्रिक है।
टॉफी

1
लिंक अब मर चुका है।
CBHacking

1

यद्यपि यह ऑपरेटरों को करना संभव नहीं है, आप हमेशा ऐड (या कॉनसैट), घटाना और तरीकों की तुलना कर सकते हैं ...।

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;    

namespace Whatever.Test
{
    public static class Extensions
    {
        public static int Compare(this MyObject t1, MyObject t2)
        {
            if(t1.SomeValueField < t2.SomeValueField )
                return -1;
            else if (t1.SomeValueField > t2.SomeValueField )
            {
                return 1;
            }
            else
            {
                return 0;
            }
        }

        public static MyObject Add(this MyObject t1, MyObject t2)
        {
            var newObject = new MyObject();
            //do something  
            return newObject;

        }

        public static MyObject Subtract(this MyObject t1, MyObject t2)
        {
            var newObject= new MyObject();
            //do something
            return newObject;    
        }
    }


}

1

हा! मैं sb + = (चीज) के लिए "एक्सटेंशन ऑपरेटर ओवरलोडिंग" को बिल्कुल उसी इच्छा के साथ देख रहा था।

यहां उत्तर पढ़ने के बाद (और यह देखते हुए कि उत्तर "नहीं" है), मेरी विशेष आवश्यकताओं के लिए, मैं एक विस्तार विधि के साथ गया, जो sb.AppendLine और sb.AppendFormat को जोड़ती है, और या तो की तुलना में अधिक स्पष्ट दिखता है।

public static class SomeExtensions
{
    public static void Line(this StringBuilder sb, string format, params object[] args)
    {
        string s = String.Format(format + "\n", args);
        sb.Append(s);
    }

}

इसलिए,

sb.Line("the first thing is {0}",first);
sb.Line("the second thing is {0}", second);

सामान्य उत्तर नहीं है, लेकिन भविष्य के चाहने वालों के लिए इस तरह की चीज के लिए रुचि हो सकती है।


4
मुझे लगता है कि अगर आप इसके AppendLineबजाय इसका नाम रखते तो आपका एक्सटेंशन तरीका बेहतर होता Line
डेविड आरआर सिप

0

एक रैपर और एक्सटेंशन के साथ इसे रिग करना संभव है लेकिन इसे ठीक से करना असंभव है। आप कचरे के साथ समाप्त होते हैं जो उद्देश्य को पूरी तरह से हरा देता है। मैं यहाँ कहीं पर एक पोस्ट है कि यह करता है, लेकिन यह बेकार है।

Btw सभी संख्यात्मक रूपांतरण स्ट्रिंग बिल्डर में कचरा पैदा करते हैं जिन्हें ठीक करने की आवश्यकता होती है। मुझे इसके लिए एक रैपर लिखना था जो काम करता है और मैं इसका उपयोग करता हूं। जो कि सोचने लायक है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.