तर्क के रूप में सी # पासिंग फंक्शन


141

मैंने C # में एक फ़ंक्शन लिखा है जो एक संख्यात्मक भेदभाव करता है। यह इस तरह दिख रहा है:

public double Diff(double x)
{
    double h = 0.0000001;

    return (Function(x + h) - Function(x)) / h;
}

मैं किसी भी फंक्शन में पास होना चाहूंगा, जैसे:

public double Diff(double x, function f)
{
    double h = 0.0000001;

    return (f(x + h) - f(x)) / h;
}

मुझे लगता है कि प्रतिनिधियों के साथ यह संभव है (शायद?) लेकिन मुझे यकीन नहीं है कि उनका उपयोग कैसे किया जाए।

किसी भी तरह की सहायता का स्वागत किया जाएगा।

जवाबों:


146

ऊपर बताए गए कार्यों के अनुसार फ़ंक का उपयोग करना, लेकिन ऐसे प्रतिनिधि भी हैं जो समान कार्य करते हैं और नामकरण के भीतर इरादे को भी परिभाषित करते हैं:

public delegate double MyFunction(double x);

public double Diff(double x, MyFunction f)
{
    double h = 0.0000001;

    return (f(x + h) - f(x)) / h;
}

public double MyFunctionMethod(double x)
{
    // Can add more complicated logic here
    return x + 10;
}

public void Client()
{
    double result = Diff(1.234, x => x * 456.1234);
    double secondResult = Diff(2.345, MyFunctionMethod);
}

5
3.5 और बाद में, फंक <> और प्रतिनिधि विनिमेय हैं, और इसका मतलब है कि अनाम प्रतिनिधियों और लंबदा (जो गुमनाम प्रतिनिधियों के लिए सिंथेटिक चीनी हैं) का भी उपयोग किया जा सकता है। तो यह वास्तव में मायने नहीं रखता है कि क्या आप पैरामीटर को फंक <डबल, डबल> या एक प्रतिनिधि के रूप में निर्दिष्ट करते हैं जो एक डबल लेता है और एक डबल लौटाता है। नामांकित प्रतिनिधि का एकमात्र वास्तविक लाभ आपको xml-doc टिप्पणियों को जोड़ने की क्षमता देता है; वर्णनात्मक नाम केवल प्रकार के बजाय पैरामीटर नाम के रूप में लागू करना आसान है।
कीथ्स

3
मेरा तर्क है कि विधि प्रोटोटाइप अभी भी कोड को फंक <x, y> से अधिक पठनीय बनाता है - यह सिर्फ नामकरण नहीं है जो कोड को पठनीय बनाता है और जैसा कि आप कहते हैं कि आपको लैम्बडा को कोड में पारित करने से नहीं रोकता है।
इयान जॉनसन

यदि प्रतिनिधि प्रकार का नामकरण कोड स्पष्टता के लिए इतना महत्वपूर्ण है, तो मुझे लगता है कि ज्यादातर मामलों में मैं एक इंटरफ़ेस और कार्यान्वयन के लिए झुकाव होगा।
क्वेंटिन-स्टारिन

@qstarin यह केवल प्रतिनिधि का नामकरण नहीं है, बल्कि उन तर्कों का नामकरण है जो विधि को लेना चाहिए, खासकर यदि वे केवल मूल प्रकार हैं। आप सही कह रहे हैं, ज्यादातर मैं प्रतिनिधियों के ऊपर इंटरफेस का उपयोग करता हूं
इयान जॉनसन

अगर मैं इनमें से एक को एक सामान्य फ़ंक्शन के रूप में बना रहा हूं जो सामान्य कार्यक्षमता प्रदान करता है, (एक नहीं-तो-सामान्य रिटर्न प्रकार के साथ) सब कुछ तब तक काम करता है जब तक मैं इसे शून्य के साथ उपयोग करने की कोशिश नहीं करता। क्या मुझे वास्तव में फंक की बजाय एक्शन का उपयोग करके डुप्लिकेट फ़ंक्शन बनाने की आवश्यकता है या क्या एक बेहतर तरीका है?
दान चेस

175

.Net (v2 और बाद के) में कुछ सामान्य प्रकार हैं जो प्रतिनिधियों को बहुत आसान बनाते हैं।

रिटर्न प्रकारों वाले कार्यों के लिए, फंक <> है और बिना रिटर्न प्रकारों के कार्यों के लिए एक्शन <> है।

फंक और एक्शन दोनों को 0 से 4 मापदंडों तक लेने के लिए घोषित किया जा सकता है। उदाहरण के लिए, फंक <डबल, इंट> एक डबल पैरामीटर के रूप में लेता है और एक इंट लौटाता है। क्रिया <डबल, डबल, डबल> पैरामीटर के रूप में तीन डबल्स लेता है और कुछ भी नहीं देता है (शून्य)।

तो आप फंक लेने के लिए अपने डिफ फ़ंक्शन को घोषित कर सकते हैं:

public double Diff(double x, Func<double, double> f) {
    double h = 0.0000001;

    return (f(x + h) - f(x)) / h;
}

और फिर आप इसे ऐसा कहते हैं, बस इसे उस फ़ंक्शन का नाम देते हैं जो आपके फ़नक या एक्शन के हस्ताक्षर को फिट करता है:

double result = Diff(myValue, Function);

आप फ़ंक्शन को लैम्ब्डा सिंटैक्स के साथ इन-लाइन भी लिख सकते हैं:

double result = Diff(myValue, d => Math.Sqrt(d * 3.14));

29
.NET 4 में, दोनों को अपडेट किया गया है Funcऔर 16 मापदंडों तक कीAction अनुमति दी गई है
जोएल म्यूलर

5
करने के लिए एक बहुत अच्छी बात Func<double, double>यह है कि इनपुट फ़ंक्शन का पहला व्युत्पन्न है, संख्यात्मक रूप से गणना की जाती है। return x => (f(x + h) - f(x)) / h;आप एक अधिभार भी लिख सकते nहैं जिसने इनपुट फ़ंक्शन के वें व्युत्पन्न को वापस कर दिया ।
ऐनी

15
public static T Runner<T>(Func<T> funcToRun)
{
    //Do stuff before running function as normal
    return funcToRun();
}

उपयोग:

var ReturnValue = Runner(() => GetUser(99));

मैं उत्सुक हूं, जेनेरिक टाइप पैरामीटर क्यों?
kdbanman

2
मुझे यह त्रुटि मिल रही है: विधि 'रनर <टी> (फंक <टी>)' के प्रकार के तर्क उपयोग से हीन नहीं हो सकते। प्रकार तर्कों को स्पष्ट रूप से निर्दिष्ट करने का प्रयास करें।
DermFrench 10

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