- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我尝试反汇编 C# 创建的可执行文件,但无法得出结论。我想知道的是,对于 CLR,c# 的委托(delegate)是否真的是特殊实体或只是一个编译器糖?
我问这个是因为我正在实现一种编译为 C# 的语言,对我来说,将匿名函数编译为类比编译为委托(delegate)更有趣。但是我不想使用以后我会后悔的设计,因为它们可能会占用更多内存(我认为 Java 的 PermGen 是我提问的基础。尽管我知道 CLR 没有这样的东西)。
谢谢!
--编辑
更清楚一点,我想知道之间是否有(以及有什么)区别:
void Main()
{
Func<int, int, int> add = delegate(int a, int b) {return a + b;};
}
例如
class AnonFuncion__1219023 : Fun3
{
public override int invoke(int a, int b)
{
return a + b;
}
}
-- 编辑
我认为两者之间可能存在很大差异:
class Program
{
static int add(int a, int b)
{
return a + b;
}
static void Main()
{
Func<int, int, int> add = Program.add;
}
}
和
class Function__432892 : Fun3
{
public override int invoke(int a, int b)
{
return Program.add(a, b);
}
}
不过,我在某处读到语法 Func<int, int, int> add = Program.add;
只是Func<int, int, int> add = delegate(int a, int b) { return Program.add; };
的糖.但我真的不知道这是不是真的。我还可以看到 C# 编译器已经缓存了所有这些实例,因此它们只被构造一次。不过,我可以用我的编译器做同样的事情。
最佳答案
我很惊讶您无法通过反汇编可执行文件得出结论。让我们看一些非常简单的东西:
using System;
class A
{
int _x;
public A(int x)
{
_x = x;
}
public void Print(int y)
{
Console.WriteLine(_x + y);
}
}
interface IPseudoDelegateVoidInt
{
void Call(int y);
}
class PseudoDelegateAPrint : IPseudoDelegateVoidInt
{
A _target;
public PseudoDelegateAPrint(A target)
{
_target = target;
}
public void Call(int y)
{
_target.Print(y);
}
}
class Program
{
delegate void RealVoidIntDelegate(int x);
static void Main()
{
A a = new A(5);
IPseudoDelegateVoidInt pdelegate = new PseudoDelegateAPrint(a);
RealVoidIntDelegate rdelegate = new RealVoidIntDelegate(a.Print);
pdelegate.Call(2);
rdelegate(2);
}
}
如果我们反汇编这个我们得到
// Microsoft (R) .NET Framework IL Disassembler. Version 4.0.30319.1
// Copyright (c) Microsoft Corporation. All rights reserved.
// Metadata version: v4.0.30319
.assembly extern mscorlib
{
.publickeytoken = (B7 7A 5C 56 19 34 E0 89 ) // .z\V.4..
.ver 4:0:0:0
}
.assembly del
{
.custom instance void [mscorlib]System.Runtime.CompilerServices.CompilationRelaxationsAttribute::.ctor(int32) = ( 01 00 08 00 00 00 00 00 )
.custom instance void [mscorlib]System.Runtime.CompilerServices.RuntimeCompatibilityAttribute::.ctor() = ( 01 00 01 00 54 02 16 57 72 61 70 4E 6F 6E 45 78 // ....T..WrapNonEx
63 65 70 74 69 6F 6E 54 68 72 6F 77 73 01 ) // ceptionThrows.
.hash algorithm 0x00008004
.ver 0:0:0:0
}
.module del.exe
// MVID: {87A2A843-A5F2-4D40-A96D-9940579DE26E}
.imagebase 0x00400000
.file alignment 0x00000200
.stackreserve 0x00100000
.subsystem 0x0003 // WINDOWS_CUI
.corflags 0x00000001 // ILONLY
// Image base: 0x0000000000B60000
// =============== CLASS MEMBERS DECLARATION ===================
.class private auto ansi beforefieldinit A
extends [mscorlib]System.Object
{
.field private int32 _x
.method public hidebysig specialname rtspecialname
instance void .ctor(int32 x) cil managed
{
// Code size 17 (0x11)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: nop
IL_0007: nop
IL_0008: ldarg.0
IL_0009: ldarg.1
IL_000a: stfld int32 A::_x
IL_000f: nop
IL_0010: ret
} // end of method A::.ctor
.method public hidebysig instance void
Print(int32 y) cil managed
{
// Code size 16 (0x10)
.maxstack 8
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldfld int32 A::_x
IL_0007: ldarg.1
IL_0008: add
IL_0009: call void [mscorlib]System.Console::WriteLine(int32)
IL_000e: nop
IL_000f: ret
} // end of method A::Print
} // end of class A
.class interface private abstract auto ansi IPseudoDelegateVoidInt
{
.method public hidebysig newslot abstract virtual
instance void Call(int32 y) cil managed
{
} // end of method IPseudoDelegateVoidInt::Call
} // end of class IPseudoDelegateVoidInt
.class private auto ansi beforefieldinit PseudoDelegateAPrint
extends [mscorlib]System.Object
implements IPseudoDelegateVoidInt
{
.field private class A _target
.method public hidebysig specialname rtspecialname
instance void .ctor(class A target) cil managed
{
// Code size 17 (0x11)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: nop
IL_0007: nop
IL_0008: ldarg.0
IL_0009: ldarg.1
IL_000a: stfld class A PseudoDelegateAPrint::_target
IL_000f: nop
IL_0010: ret
} // end of method PseudoDelegateAPrint::.ctor
.method public hidebysig newslot virtual final
instance void Call(int32 y) cil managed
{
// Code size 15 (0xf)
.maxstack 8
IL_0000: nop
IL_0001: ldarg.0
IL_0002: ldfld class A PseudoDelegateAPrint::_target
IL_0007: ldarg.1
IL_0008: callvirt instance void A::Print(int32)
IL_000d: nop
IL_000e: ret
} // end of method PseudoDelegateAPrint::Call
} // end of class PseudoDelegateAPrint
.class private auto ansi beforefieldinit Program
extends [mscorlib]System.Object
{
.class auto ansi sealed nested private RealVoidIntDelegate
extends [mscorlib]System.MulticastDelegate
{
.method public hidebysig specialname rtspecialname
instance void .ctor(object 'object',
native int 'method') runtime managed
{
} // end of method RealVoidIntDelegate::.ctor
.method public hidebysig newslot virtual
instance void Invoke(int32 x) runtime managed
{
} // end of method RealVoidIntDelegate::Invoke
.method public hidebysig newslot virtual
instance class [mscorlib]System.IAsyncResult
BeginInvoke(int32 x,
class [mscorlib]System.AsyncCallback callback,
object 'object') runtime managed
{
} // end of method RealVoidIntDelegate::BeginInvoke
.method public hidebysig newslot virtual
instance void EndInvoke(class [mscorlib]System.IAsyncResult result) runtime managed
{
} // end of method RealVoidIntDelegate::EndInvoke
} // end of class RealVoidIntDelegate
.method private hidebysig static void Main() cil managed
{
.entrypoint
// Code size 45 (0x2d)
.maxstack 3
.locals init (class A V_0,
class IPseudoDelegateVoidInt V_1,
class Program/RealVoidIntDelegate V_2)
IL_0000: nop
IL_0001: ldc.i4.5
IL_0002: newobj instance void A::.ctor(int32)
IL_0007: stloc.0
IL_0008: ldloc.0
IL_0009: newobj instance void PseudoDelegateAPrint::.ctor(class A)
IL_000e: stloc.1
IL_000f: ldloc.0
IL_0010: ldftn instance void A::Print(int32)
IL_0016: newobj instance void Program/RealVoidIntDelegate::.ctor(object,
native int)
IL_001b: stloc.2
IL_001c: ldloc.1
IL_001d: ldc.i4.2
IL_001e: callvirt instance void IPseudoDelegateVoidInt::Call(int32)
IL_0023: nop
IL_0024: ldloc.2
IL_0025: ldc.i4.2
IL_0026: callvirt instance void Program/RealVoidIntDelegate::Invoke(int32)
IL_002b: nop
IL_002c: ret
} // end of method Program::Main
.method public hidebysig specialname rtspecialname
instance void .ctor() cil managed
{
// Code size 7 (0x7)
.maxstack 8
IL_0000: ldarg.0
IL_0001: call instance void [mscorlib]System.Object::.ctor()
IL_0006: ret
} // end of method Program::.ctor
} // end of class Program
// =============================================================
// *********** DISASSEMBLY COMPLETE ***********************
// WARNING: Created Win32 resource file C:\Users\logan\del.res
如您所见,RealVoidIntDelegate 变成“只是”另一个类。他们称它为Invoke
而不是Call
,他们没有使用接口(interface)但也没有涉及特殊的指令,这是相同的基本思想。
为了详细说明“轻量级”的概念,委托(delegate)并不比类更轻,因为给定的委托(delegate)是一个类。特别是在函数字面量语法的情况下,它们真的不能轻很多。然而,对于“使用这些 args 在此对象上调用此方法”的情况,调用和创建给定的委托(delegate)在编译为 C# 时可能比本地委托(delegate)更轻。
关于c# - 委托(delegate)是否比类更轻量级?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5052390/
我有一个功能是转换 ADO Recordset 进入html: class function RecordsetToHtml(const rs: _Recordset): WideString; 该函
经过几天的研究和讨论,我想出了这种方法来收集访客的熵(你可以看到我的研究历史here) 当用户访问时,我运行此代码: $entropy=sha1(microtime().$pepper.$_SERVE
给定一个无序列表 List ,我需要查找是否存在 String与提供的字符串匹配。 所以,我循环 for (String k : keys) { if (Utils.keysM
我已经搜索过这个问题,但没有找到我正在寻找的答案。 基本上,我想将类构造函数包装在 try/except 子句中,以便它忽略构造函数内特定类型的错误(但无论如何都会记录并打印它们)。我发现做到这一点的
我有一组三个数字,我想将一组数字与另一组数字进行比较。即,第一组中的每个数字小于另一组中的至少一个数字。需要注意的是,第一组中的下一个数字必须小于第二组中的不同数字(即,{6,1,6} 对 {8,8,
关闭。这个问题是off-topic .它目前不接受答案。 想改进这个问题吗? Update the question所以它是on-topic用于堆栈溢出。 关闭 9 年前。 Improve this
首先介绍一下背景: 我正在开发一个带有 EJB 模块和应用程序客户端模块的企业应用程序 (ear)。我还使用 hibernate JPA 来实现持久性,并使用 swingx 来实现 GUI。这些是唯一
我正在尝试在我的上网本上运行 Eclipse 以便能够为 Android 进行开发。 您可能已经猜到了,Eclipse 非常慢,并且不容易有效地开发。 我正在使用 Linux Ubuntu 并且我还有
for row, instrument in enumerate(instruments): for col, value in enumerate(instrument):
return not a and not b ^ 我如何以更好的格式表达它 最佳答案 DeMorgan's Law , 也许? return not (a or b) 我认为在这一点上已经足够简单了
我正在尝试让 Font Awesome 图标看起来更 slim https://jsfiddle.net/cliffeee/7L6ehw9r/1/ . 我尝试使用“-webkit-text-strok
假设我有一个名为 vals 的数据框,如下所示: id…………日期…………min_date…… .........最大日期 1…………2016/01/01…………2017/01/01…………2018/
是否有更 Pythonic 的方式来做到这一点?: if self.name2info[name]['prereqs'] is None: se
我有一个函数可以将一些文本打印到它接收到的 ostream&。如果 ostream 以终端为目标,我想让它适应终端宽度,否则默认为某个值。 我现在做的是: 从 ostream 中获取一个 ofstre
这个问题在这里已经有了答案: Should a retrieval method return 'null' or throw an exception when it can't produce
我有这个 bc = 'off' if c.page == 'blog': bc = 'on' print(bc) 有没有更 Pythonic(和/或更短)的方式在 Python 中编写? 最佳
输入:一个包含 50,000 行的 CSV;每行包含 910 列值 0/1。 输出:运行我的 CNN 的数据框。 我编写了一个逐行读取 CSV 的代码。对于每一行,我将数据分成两部分,称为神经元(90
据我所知,with block 会在您退出 block 后自动调用 close(),并且它通常用于确保不会忘记关闭一个文件。 好像没有技术上的区别 with open(file, 'r+') as f
我有一个使用 Entity Framework V6.1.1 的 MVC 5 网站。 Entity Framework DbContext 类和模型最初都在网站项目中。这个项目有 3 个 DbCont
我是编程新手,在尝试通过将 tableView 和关联 View 的创建移动到单独的类并将委托(delegate)和数据源从 VC 移动到单独的类来精简我的 ViewController 时遇到了一些
我是一名优秀的程序员,十分优秀!