分配免费委托或其他方式按地址调用方法?

mr.*_*r.b 11 c# mono delegates function-pointers

我需要能够使用Mono在C#中基于函数指针调用单个方法.代表工作正常,这是他们的目的,但是每次我设置委托时它们似乎分配了52个字节(不是+ =,而只是使用=设置它所以总是只有一个方法被委托引用).

这个委托每秒更改很多次,它导致GC定期启动,我想避免.

我不介意初始内存分配,但有没有办法在每次更改单个委托值时阻止分配?

如果没有,除了每次更改地址时都不会分配任何内存的委托之外,还有其他动态方法来调用C#中的方法吗?

Dav*_*wen 9

你写的任何代码都是这样的

Action action = foo.DoSomething;
Run Code Online (Sandbox Code Playgroud)

结束编译成这个

Action action = new Action(foo.DoSomething);
Run Code Online (Sandbox Code Playgroud)

这是分配的来源.没有任何完美的方法可以解决这个问题,但是要阻止缓存和重用委托所需的分配.

实施方修复

您可以通过为每个方法创建委托来在实现方面实现此目的.

public class Foo
{
    public void DoSomething() { /*nop*/ }

    private Action _doSomethingDelegate;
    public Action DoSomethingDelegate
    {
        get { return _doSomethingDelegate ?? (_doSomethingDelegate = DoSomething); }
    }
}
Run Code Online (Sandbox Code Playgroud)

那么你只需引用现有的委托而不是方法

Action action = foo.DoSomethingDelegate;
Run Code Online (Sandbox Code Playgroud)

缓存修复

另一个选择是使用某种缓存类,但这会引入一堆对象生命周期问题,这些问题在游戏场景中可能是您​​不想要的.这是一个粗略的实现是真实的可能想要使用弱引用.

public static class DelegateCache
{
    private static readonly Dictionary<object, Dictionary<string, Delegate>> Cache = new Dictionary<object, Dictionary<string, Delegate>>();

    private static Dictionary<string, Delegate> GetObjectCache(object instance)
    {
        Dictionary<string, Delegate> delegates;
        if (!Cache.TryGetValue(instance, out delegates))
        {
            Cache[instance] = delegates = new Dictionary<string, Delegate>();
        }
        return delegates;
    }

    public static T GetDelegate<T>(object instance, string method)
        where T: class
    {
        var delegates = GetObjectCache(instance);
        Delegate del;
        if (!delegates.TryGetValue(method, out del))
        {
            delegates[method] = del = Delegate.CreateDelegate(typeof(T), instance, method);
        }
        return del as T;
    }
}
Run Code Online (Sandbox Code Playgroud)

使用它将看起来像这样

Action action = DelegateCache.GetDelegate<Action>(foo, "DoSomething");
Run Code Online (Sandbox Code Playgroud)

摘要

运行一些测试这两种方法每个对象/方法对只有一个分配.我可能会去实施方面修复它虽然很多工作,但它更清洁.如果有很多方法并且您计划添加更多方法,则可以使用T4生成具有方法的委托实现的分部类.