c# - Changing Delegate signature in library to omit an argument does not break applications using it -


consider following code in class library:

public class service {     public delegate string formatter(string s1, string s2);      public void print(formatter f)     {         console.writeline(f("a", "b"));     } } 

and here's console application uses it:

static void main(string[] args) {     s = new service();     s.print(concat); }  static string concat(string s1, string s2) {     return string.format("{0}-{1}", s1, s2); } 

so far prints "a-b", 1 expect.

now, change class library follows:

public class service {     public delegate string formatter(string s1);      public void print(formatter f)     {         console.writeline(f("a"));     } } 

i.e. removed 1 parameter delegate. compile class library , overwrite dll sitting next console app (console app not recompiled). i'd expect breaking change in library , if execute app, finds mismatch, resulting in runtime exception.

in contrast, when run app there's no exception @ all, , stunning output "-a". when debug, can see concat method (with 2 parameters) called, call stack level below shows print calling f("a") (one parameter), no error indication anywhere. interestingly, in concat s1 null, s2 "a".

i played around different changes signature (adding parameters, changing parameter type) same result. when changed type of s2 string int got exception, not when concat method called, when tried call string.format.

i tried .net target framework 4.5.1 , 3.5, x86 , x64.

can answer whether expected behaviour or bug? seems pretty dangerous me.

here's simpler repro - basically, i'm using "under hood" constructor on delegate type (the 1 il uses) pass method target wrong signature, and... works fine (by mean doesn't throw exception - behaves code):

using system;  static class p {     static void main()     {         // resolve (object, intptr) ctor         var ctor = typeof(func<string, string>).getconstructors()[0];          // resolve target method         var mhandle = typeof(p).getmethod(nameof(concat))             .methodhandle.getfunctionpointer();         object target = null; // because: static          // create delegate instance         var del = (func<string, string>)ctor.invoke(new object[] { target, mhandle });         var result = del("abc");         console.writeline(result); // "-abc"     }     public static string concat(string s1, string s2)     {         return string.format("{0}-{1}", s1, s2);     } } 

this not explanation. might helpful if want ask more clr-expert! have expected delegate constructor have complained loudly target being incorrect.

at guess (pure speculation), case of: if you're passing intptr (native int), you're entirely on own - code fastest thing possible. seem nasty trap unwary, though!

as why s2 has value , s1 empty: guess because stack builds down (not up), hence in 2 parameter method, arg1 parameter immediately adjacent previous position on stack. when pass single value instead of two, put 1 value underneath, s2 has value, , s1 undefined (could garbage previous code).


Comments

Popular posts from this blog

Command prompt result in label. Python 2.7 -

javascript - How do I use URL parameters to change link href on page? -

amazon web services - AWS Route53 Trying To Get Site To Resolve To www -