请考虑类库中的以下代码:
public class Service
{
public delegate string Formatter(string s1, string s2);
public void Print(Formatter f)
{
Console.WriteLine(f("a", "b"));
}
}
Run Code Online (Sandbox Code Playgroud)
这是一个使用它的控制台应用程序:
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);
}
Run Code Online (Sandbox Code Playgroud)
到目前为止,它打印" ab ",正如人们所期望的那样.
现在,我按如下方式更改类库:
public class Service
{
public delegate string Formatter(string s1);
public void Print(Formatter f)
{
Console.WriteLine(f("a"));
}
}
Run Code Online (Sandbox Code Playgroud)
即我从委托中删除了一个参数.我只编译类库并覆盖控制台应用程序旁边的dll(控制台应用程序未重新编译).我希望这是库中的一个重大变化,如果我执行应用程序,它会发现不匹配,导致一些运行时异常.
相比之下,当我运行应用程序时,根本没有例外,我得到令人惊叹的输出" -a ".当我调试时,我可以看到调用Concat方法(带有2个参数),下面的调用堆栈级别显示Print调用f("a")(一个参数),任何地方都没有错误指示.最有趣的是,在Concat中,s1为null,s2为"a".
我也使用相同的结果,对签名(添加参数,更改参数类型)进行了不同的更改.当我将s2的类型从string更改为int时,我得到了一个异常,但是当调用Concat方法时却没有,但是当它尝试调用string.Format时.
我尝试使用.NET目标框架4.5.1和3.5,x86和x64.
任何人都可以回答这是预期的行为还是错误?这对我来说似乎很危险.
这是一个更简单的repro - 基本上,我在委托类型(IL使用的那个)上使用"引擎盖下"构造函数来传递带有错误签名的方法目标,并且......它工作正常(通过它我的意思是它不会抛出异常 - 它的行为就像你的代码一样):
using System;
static class P
{
static void Main()
{
// resolve the (object, IntPtr) ctor
var ctor = typeof(Func<string, string>).GetConstructors()[0];
// resolve the 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);
}
}
Run Code Online (Sandbox Code Playgroud)
这不是一个真正的解释.但如果你想问一个更多的CLR专家可能会有所帮助!我本来预期的委托构造函数有关于目标是不正确大声抱怨.
在一个猜测(纯猜测),它是一个例子:如果你传递一个IntPtr(本机int),那么你完全靠自己 - 代码尽可能快.不过,对于粗心的人来说,这似乎是一个令人讨厌的陷阱!
至于为什么s2有值并且s1是空的:我想这是因为堆栈向下(不是向上),因此在双参数方法中,arg1是紧邻堆栈上的前一个位置的参数.当我们传递一个值而不是两个时,我们只在下面放一个值,因此s2有一个值,并且s1是未定义的(可能是以前代码中的垃圾).
| 归档时间: |
|
| 查看次数: |
391 次 |
| 最近记录: |