gpt4 book ai didi

c# - 委托(delegate)是否比类更轻量级?

转载 作者:太空狗 更新时间:2023-10-29 18:16:58 27 4
gpt4 key购买 nike

我尝试反汇编 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/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com