C # में इनलाइन फ़ंक्शन कैसे करें


97

मैं Linq को XML का उपयोग कर रहा हूं

new XElement("Prefix", Prefix == null ? "" : Prefix)

लेकिन मैं इसे xml में जोड़ने से पहले उपसर्ग के लिए कुछ गणना करना चाहता हूं, जैसे रिक्त स्थान, विशेष चार्ट, कुछ गणना आदि को समाप्त करना।

मैं फ़ंक्शंस बनाना नहीं चाहता क्योंकि यह मेरे प्रोग्राम के किसी अन्य भाग पर किसी भी मदद का नहीं होगा, लेकिन यह है, इसलिए इनलाइन फ़ंक्शंस बनाने का कोई तरीका है ??


5
न केवल एक समारोह बनाने से खुद को रोकें क्योंकि यह किसी अन्य जगह से नहीं बुलाया जाएगा। फ़ंक्शंस का उपयोग कोड को साफ करने के लिए भी किया जा सकता है (यदि आपके पास कई प्रक्रियाओं को फैलाने वाली एक बड़ी प्रक्रिया है, जो इसे कार्यों में तोड़ती है, तो यह अधिक पठनीय है) और स्व दस्तावेज़ (बस एक फ़ंक्शन का नामकरण ठीक से पाठक को जानकारी दे सकता है।)
जो

14
यदि आप Google से यहां आए हैं और जानना चाहते हैं कि c # में इनलाइन कार्यों का अनुकरण कैसे किया जाए, तो यहां जाएं: stackoverflow.com/questions/473782/inline-functions-in-c नीचे दिए गए उत्तर "इनलाइन" फ़ंक्शन से संबंधित नहीं हैं शब्द के सही अर्थों में, और c # में सत्य इनलाइन फ़ंक्शन भी नहीं हैं, लेकिन ऊपर दिया गया लिंक एक कंपाइलर ऑप्टिमाइज़ेशन प्रदान करता है जिसका उपयोग किया जा सकता है।
जेम्सहॉक्स

धन्यवाद जेम्स, सवाल शीर्षक वास्तव में भ्रामक है।
ज़ार शारदान

जवाबों:


226

हां, C # उसका समर्थन करता है। कई वाक्यविन्यास उपलब्ध हैं।

  • बेनामी तरीके C # 2.0 में जोड़े गए:

    Func<int, int, int> add = delegate(int x, int y)
    {
        return x + y;
    };
    Action<int> print = delegate(int x)
    {
        Console.WriteLine(x);
    }
    Action<int> helloWorld = delegate // parameters can be elided if ignored
    {
        Console.WriteLine("Hello world!");
    }
    
  • लैम्ब्डा C # 3.0 में नए हैं और दो फ्लेवर में आते हैं।

    • अभिव्यक्ति लंबोदर:

      Func<int, int, int> add = (int x, int y) => x + y; // or...
      Func<int, int, int> add = (x, y) => x + y; // types are inferred by the compiler
      
    • कथन लंबोदर:

      Action<int> print = (int x) => { Console.WriteLine(x); };
      Action<int> print = x => { Console.WriteLine(x); }; // inferred types
      Func<int, int, int> add = (x, y) => { return x + y; };
      
  • स्थानीय कार्यों को C # 7.0 के साथ पेश किया गया है:

    int add(int x, int y) => x + y;
    void print(int x) { Console.WriteLine(x); }
    

इनके लिए मूल रूप से दो अलग-अलग प्रकार हैं: Funcऔर ActionFuncमान लौटाते हैं, लेकिन Actionहै नहीं। A का अंतिम प्रकार पैरामीटर Funcरिटर्न प्रकार है; अन्य सभी पैरामीटर प्रकार हैं।

विभिन्न नामों के साथ समान प्रकार हैं, लेकिन उन्हें इनलाइन घोषित करने के लिए सिंटैक्स समान है। इसका एक उदाहरण है Comparison<T>, जो लगभग बराबर है Func<T, T, int>

Func<string, string, int> compare1 = (l,r) => 1;
Comparison<string> compare2 = (l, r) => 1;
Comparison<string> compare3 = compare1; // this one only works from C# 4.0 onwards

इन्हें सीधे लागू किया जा सकता है जैसे कि वे नियमित तरीके थे:

int x = add(23, 17); // x == 40
print(x); // outputs 40
helloWorld(x); // helloWorld has one int parameter declared: Action<int>
               // even though it does not make any use of it.

4
मुझे यह उत्तर समझ में नहीं आता है। अपने उदाहरण में, वह नई XElement ("उपसर्ग", उपसर्ग => newPrefix) इनलाइन घोषित करता है। ये सभी उत्तर एक नए फ़ंक्शन को घोषित करने के लिए राशि देते हैं। सिर्फ एक नए समारोह की घोषणा क्यों नहीं?
मैथ्यू जेम्स डेविस

3
क्योंकि: 1. अलग-अलग घोषणाओं को खोजने की तुलना में विधि पढ़ने के इनलाइन फ़ंक्शन का तर्क बहुत आसान है। इनलाइन फ़ंक्शंस का उपयोग करते समय आपको अक्सर कम कोड लिखने की आवश्यकता होती है
वलोडिमिर

35

C # 7 स्थानीय कार्यों के लिए समर्थन जोड़ता है

यहां एक स्थानीय फ़ंक्शन का उपयोग करके पिछले उदाहरण दिया गया है

void Method()
{
    string localFunction(string source)
    {
        // add your functionality here
        return source ;
    };

   // call the inline function
   localFunction("prefix");
}

29

आपके प्रश्न का उत्तर "इनलाइन फ़ंक्शन" के आधार पर हां और नहीं में है, जो आपके द्वारा निर्भर करता है। यदि आप इस शब्द का उपयोग कर रहे हैं जैसे कि यह C ++ विकास में उपयोग किया जाता है तो उत्तर नहीं है, आप ऐसा नहीं कर सकते हैं - यहां तक ​​कि एक लंबोदर अभिव्यक्ति एक फ़ंक्शन कॉल है। हालांकि यह सच है कि आप सी # में फ़ंक्शन घोषणाओं को बदलने के लिए इनलाइन लैम्ब्डा अभिव्यक्तियों को परिभाषित कर सकते हैं, फिर भी कंपाइलर एक अनाम फ़ंक्शन बना रहा है।

यहाँ कुछ वास्तव में सरल कोड है जो मैं इसका परीक्षण करता था (VS2015):

    static void Main(string[] args)
    {
        Func<int, int> incr = a => a + 1;
        Console.WriteLine($"P1 = {incr(5)}");
    }

संकलक क्या उत्पन्न करता है? मैंने ILSpy नामक एक निफ्टी टूल का उपयोग किया जो वास्तविक IL असेंबली को दिखाता है। एक नज़र रखना (मैंने बहुत सारे वर्ग सेटअप सामान छोड़ दिए हैं)

यह मुख्य कार्य है:

        IL_001f: stloc.0
        IL_0020: ldstr "P1 = {0}"
        IL_0025: ldloc.0
        IL_0026: ldc.i4.5
        IL_0027: callvirt instance !1 class [mscorlib]System.Func`2<int32, int32>::Invoke(!0)
        IL_002c: box [mscorlib]System.Int32
        IL_0031: call string [mscorlib]System.String::Format(string, object)
        IL_0036: call void [mscorlib]System.Console::WriteLine(string)
        IL_003b: ret

उन पंक्तियों को देखें IL_0026 और IL_0027? वे दो निर्देश संख्या 5 को लोड करते हैं और एक फ़ंक्शन को कॉल करते हैं। फिर IL_0031 और IL_0036 प्रारूप और परिणाम प्रिंट करें।

और यहाँ फ़ंक्शन कहा जाता है:

        .method assembly hidebysig 
            instance int32 '<Main>b__0_0' (
                int32 a
            ) cil managed 
        {
            // Method begins at RVA 0x20ac
            // Code size 4 (0x4)
            .maxstack 8

            IL_0000: ldarg.1
            IL_0001: ldc.i4.1
            IL_0002: add
            IL_0003: ret
        } // end of method '<>c'::'<Main>b__0_0'

यह वास्तव में एक छोटा कार्य है, लेकिन यह एक कार्य है।

क्या यह अनुकूलन के लिए किसी भी प्रयास के लायक है? नाह। हो सकता है कि यदि आप इसे हजारों बार एक सेकंड में बुला रहे हों, लेकिन यदि प्रदर्शन इतना महत्वपूर्ण है, तो आपको कार्य करने के लिए C / C ++ में लिखे गए मूल कोड पर विचार करना चाहिए।

मेरे अनुभव में पठनीयता और स्थिरता हमेशा कुछ माइक्रोसेकंड गति में लाभ के लिए अनुकूलन की तुलना में लगभग अधिक महत्वपूर्ण है। अपने कोड को पठनीय बनाने और चर स्कूपिंग को नियंत्रित करने और प्रदर्शन के बारे में चिंता न करने के लिए फ़ंक्शन का उपयोग करें।

"समयपूर्व अनुकूलन प्रोग्रामिंग में सभी बुराई (या कम से कम अधिकांश) की जड़ है।" - डोनाल्ड नथ

"एक प्रोग्राम जो सही ढंग से नहीं चलता है उसे तेज़ दौड़ने की ज़रूरत नहीं है" - मुझे


3
यह C # फ़ंक्शन को इनलाइन करने के लिए एक शीर्ष Google हिट है। आप कहते हैं "हो सकता है कि अगर आप इसे हजारों बार एक सेकंड में बुला रहे हैं", और लगता है कि क्या - मैं इसे 4 मिलियन बार एक सेकंड में कॉल कर रहा हूं, तो हाँ ... इनलाइनिंग शायद उपयोगी होगी (और कोड की पठनीयता को बढ़ाएँ बनाम मैं ऐसा करने वाला हूं: 16 स्थानों में एक फ़ंक्शन के मैनुअल अनरोलिंग)।
एडम

17

हाँ।

आप गुमनाम तरीके या लंबोदर भाव बना सकते हैं :

Func<string, string> PrefixTrimmer = delegate(string x) {
    return x ?? "";
};
Func<string, string> PrefixTrimmer = x => x ?? "";

आपके उत्तर के लिए धन्यवाद, क्या आप उत्तर पर थोड़ा और विस्तार कर सकते हैं, लांबा एक, मेरा मतलब है codeफंक <string, string> PrefixTrimmer = x => x ?? ""; codeयह करने के लिए नए im और मैं वास्तव में बहुत अच्छी तरह से MSDN डॉक्टर
जो Dixon

2
@ जो: x ?? ""अशक्त करने वाला ऑपरेटर है। msdn.microsoft.com/en-us/library/ms173224.aspx
SLaks

में x => (something), xएक पैरामीटर है, और (something)वापसी मान है।
SLACs


2
@ हेलफ्रोस्ट: प्रश्न पढ़ें। वह C ++ स्टाइल इनलाइन फ़ंक्शन के बारे में नहीं पूछ रहा है। मैं फ़ंक्शंस नहीं बनाना चाहता क्योंकि यह मेरे कार्यक्रम के किसी अन्य भाग पर किसी भी मदद का नहीं होगा लेकिन यह
SLaks 16

5

आप फंक का उपयोग कर सकते हैं जो एक ऐसे तरीके को एनकैप्सुलेट करता है जिसमें एक पैरामीटर होता है और TResult पैरामीटर द्वारा निर्दिष्ट प्रकार का मान लौटाता है।

void Method()
{
    Func<string,string> inlineFunction = source => 
    {
        // add your functionality here
        return source ;
     };


    // call the inline function
   inlineFunction("prefix");
}

4

केवल अंदरूनी तरीकों से ही नहीं, इसे कक्षाओं के अंदर भी इस्तेमाल किया जा सकता है।

class Calculator
    {
        public static int Sum(int x,int y) => x + y;
        public static Func<int, int, int>  Add = (x, y) => x + y;
        public static Action<int,int> DisplaySum = (x, y) => Console.WriteLine(x + y);
    }
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.