2009-05-31 12 views
27

दोनों DynamicInvoke और DynamicInvokeImpl के लिये दस्तावेज कहते हैं:डायनामिक इनवोक का उपयोग करके, और डायनेमिक इनवोक Impl का उपयोग करके सीधे प्रतिनिधि को कॉल करने के बीच क्या अंतर है?

गतिशील रूप से आह्वान (देर से बाध्य) विधि वर्तमान प्रतिनिधि द्वारा प्रतिनिधित्व किया।

मुझे लगता है कि डायनेमिक इनवोक और डायनामिक इनवोकआईएमएल तर्कों की एक विशिष्ट सूची के बजाय ऑब्जेक्ट्स की एक सरणी लेता है (जो कि देर से भाग लिया गया हिस्सा है)। लेकिन क्या यह एकमात्र अंतर है? और डायनेमिक इनवोक और डायनामिक इनवोकइम्पल के बीच क्या अंतर है।

+0

क्या आप यहां कोई जवाब स्वीकार नहीं करना चाहते हैं? मुझे पता है कि अब तक सवाल काफी पुराना है, लेकिन मुझे परेशान था कि अच्छे उम्मीदवार होने पर अभी भी कोई जवाब स्वीकार नहीं किया गया है। – NobodysNightmare

उत्तर

9

वास्तव में दोनों के बीच कोई कार्यात्मक अंतर नहीं है। यदि आप परावर्तक में कार्यान्वयन को खींचते हैं, तो आप देखेंगे कि डायनामिक इनवोक केवल तर्कसंगतता के उसी सेट के साथ डायनामिक इनवोक Impl को कॉल करता है। कोई अतिरिक्त सत्यापन नहीं किया जाता है और यह एक गैर-वर्चुअल विधि है इसलिए व्युत्पन्न वर्ग द्वारा इसके व्यवहार को बदलने का कोई मौका नहीं है। DynamicInvokeImpl एक वर्चुअल विधि है जहां सभी वास्तविक कार्य किए जाते हैं।

+0

तो दूसरे शब्दों में, डायनामिक इनवोक हमेशा आधार व्यवहार को संदर्भित करता है और डायनामिक इनवोकआईएमएल ओवरराइड हो सकता है? –

+0

@ जेसन, बिल्कुल – JaredPar

32

इसे सीधे कॉल करने के बीच मुख्य अंतर (जो Invoke(...) के लिए छोटा हाथ है) और DynamicInvoke का उपयोग प्रदर्शन है; मेरे उपाय (नीचे) से * 700 से अधिक का एक कारक।

प्रत्यक्ष/Invoke दृष्टिकोण के साथ, तर्क विधि हस्ताक्षर के माध्यम से पहले से ही मान्य हैं, और कोड सीधे उन तरीकों को पारित करने के लिए मौजूद है (मैं "आईएल के रूप में" कहूंगा, लेकिन मुझे याद है कि मुझे याद है रनटाइम इसे सीधे किसी भी आईएल के बिना प्रदान करता है)। DynamicInvoke के साथ इसे प्रतिबिंब के माध्यम से सरणी से जांचना होगा (यानी वे सभी इस कॉल के लिए उपयुक्त हैं; क्या उन्हें अनबॉक्सिंग आदि की आवश्यकता है); यह धीमा (यदि आप इसे एक तंग पाश में उपयोग कर रहे हैं), और जहां संभव हो से बचा जाना चाहिए।

उदाहरण; परिणाम पहले (मैं पिछले संपादन से LOOP गिनती वृद्धि हुई है, एक समझदार तुलना देने के लिए):

Direct: 53ms 
Invoke: 53ms 
DynamicInvoke (re-use args): 37728ms 
DynamicInvoke (per-cal args): 39911ms 

कोड के साथ:

static void DoesNothing(int a, string b, float? c) { } 
static void Main() { 
    Action<int, string, float?> method = DoesNothing; 

    int a = 23; 
    string b = "abc"; 
    float? c = null; 
    const int LOOP = 5000000; 

    Stopwatch watch = Stopwatch.StartNew(); 
    for (int i = 0; i < LOOP; i++) { 
     method(a, b, c); 
    } 
    watch.Stop(); 
    Console.WriteLine("Direct: " + watch.ElapsedMilliseconds + "ms"); 

    watch = Stopwatch.StartNew(); 
    for (int i = 0; i < LOOP; i++) { 
     method.Invoke(a, b, c); 
    } 
    watch.Stop(); 
    Console.WriteLine("Invoke: " + watch.ElapsedMilliseconds + "ms"); 

    object[] args = new object[] { a, b, c }; 
    watch = Stopwatch.StartNew(); 
    for (int i = 0; i < LOOP; i++) { 
     method.DynamicInvoke(args); 
    } 
    watch.Stop(); 
    Console.WriteLine("DynamicInvoke (re-use args): " 
     + watch.ElapsedMilliseconds + "ms"); 

    watch = Stopwatch.StartNew(); 
    for (int i = 0; i < LOOP; i++) { 
     method.DynamicInvoke(a,b,c); 
    } 
    watch.Stop(); 
    Console.WriteLine("DynamicInvoke (per-cal args): " 
     + watch.ElapsedMilliseconds + "ms"); 
} 
9

संयोग से मैं एक और अंतर पाया है।

यदि Invoke एक अपवाद फेंकता है तो इसे अपेक्षित अपवाद प्रकार से पकड़ा जा सकता है। हालांकि DynamicInvokeTargetInvokationException फेंकता है। यहां एक छोटा डेमो है:

using System; 
using System.Collections.Generic; 

namespace DynamicInvokeVsInvoke 
{ 
    public class StrategiesProvider 
    { 
     private readonly Dictionary<StrategyTypes, Action> strategies; 

     public StrategiesProvider() 
     { 
     strategies = new Dictionary<StrategyTypes, Action> 
         { 
         {StrategyTypes.NoWay,() => { throw new NotSupportedException(); }} 
         // more strategies... 
         }; 
     } 

     public void CallStrategyWithDynamicInvoke(StrategyTypes strategyType) 
     { 
     strategies[strategyType].DynamicInvoke(); 
     } 

     public void CallStrategyWithInvoke(StrategyTypes strategyType) 
     { 
     strategies[strategyType].Invoke(); 
     } 
    } 

    public enum StrategyTypes 
    { 
     NoWay = 0, 
     ThisWay, 
     ThatWay 
    } 
} 

दूसरे टेस्ट हरी जाता है, पहले एक एक TargetInvokationException सामना कर रहा है।

using System; 
using Microsoft.VisualStudio.TestTools.UnitTesting; 
using SharpTestsEx; 

namespace DynamicInvokeVsInvoke.Tests 
{ 
    [TestClass] 
    public class DynamicInvokeVsInvokeTests 
    { 
     [TestMethod] 
     public void Call_strategy_with_dynamic_invoke_can_be_catched() 
     { 
     bool catched = false; 
     try 
     { 
      new StrategiesProvider().CallStrategyWithDynamicInvoke(StrategyTypes.NoWay); 
     } 
     catch(NotSupportedException exc) 
     { 
      /* Fails because the NotSupportedException is wrapped 
      * inside a TargetInvokationException! */ 
      catched = true; 
     } 
     catched.Should().Be(true); 
     } 

     [TestMethod] 
     public void Call_strategy_with_invoke_can_be_catched() 
     { 
     bool catched = false; 
     try 
     { 
      new StrategiesProvider().CallStrategyWithInvoke(StrategyTypes.NoWay); 
     } 
     catch(NotSupportedException exc) 
     { 
      catched = true; 
     } 
     catched.Should().Be(true); 
     } 
    } 
} 
संबंधित मुद्दे

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