О производительности создания делегата c # - PullRequest
6 голосов
/ 28 июля 2011

В моем проекте много размышлений.Итак, я кэшировал делегатов в словарях.Проблема в том, что я решил использовать MethodInfo в качестве ключей dict, я пытался использовать метод поиска, который выглядит примерно так:

Func<T,R> LookUp(Func<T,R> m)
{
  return (Func<T,R>)dict[m.Method];
}
//LookUp(MyCls.Method)

Но, выполнив некоторые тесты, я выяснил,что снабжение метода LookUp адресом функции, т. е. создание переходных делегатов на лету, происходит довольно медленно, очень медленно:мой подход и написать некоторый небезопасный код (поддерживаются ли указатели функций даже в c #?) или есть альтернативные решения в стиле c # для подобных ситуаций?

Пожалуйста, помогите мне оттуда!

Ответы [ 3 ]

1 голос
/ 28 июля 2011

В целом использование интерфейсов всегда будет лучше с точки зрения производительности, чем использование делегатов / рефлексии.
Есть ли у вас контроль над объектами, чтобы использовать интерфейс вместо делегатов?

1 голос
/ 28 июля 2011

Некоторое время назад я использовал класс для агрегации событий (Mediator) в приложении Winform, в котором кэш словаря имел тип в качестве ключа и делегат в качестве значения.Класс выглядит примерно так ...

public sealed class EventAggregator
    {
        #region Fields

        private readonly Dictionary<Type, List<Object>> subscribers = new Dictionary<Type, List<Object>>();

        #endregion

        #region Public Methods

        public void Subscribe<TMessage>(Action<TMessage> handler)
        {
            if (subscribers.ContainsKey(typeof(TMessage)))
            {
                var handlers = subscribers[typeof(TMessage)];
                handlers.Add(handler);
            }
            else
            {
                var handlers = new List<Object> {handler};
                subscribers[typeof(TMessage)] = handlers;
            }
        }

        public void Unsubscribe<TMessage>(Action<TMessage> handler)
        {
            if (subscribers.ContainsKey(typeof(TMessage)))
            {
                var handlers = subscribers[typeof(TMessage)];
                handlers.Remove(handler);

                if (handlers.Count == 0)
                {
                    subscribers.Remove(typeof(TMessage));
                }
            }
        }

        public void Publish<TMessage>(TMessage message)
        {
            if (subscribers.ContainsKey(typeof(TMessage)))
            {
                var handlers = subscribers[typeof(TMessage)];
                foreach (Action<TMessage> handler in handlers)
                {
                    handler.Invoke(message);
                }
            }
        }

        #endregion
    }

, что, я думаю, похоже на то, что вы пытаетесь сделать.

Вместо того, чтобы искать самого делегата, попробуйте найти тип, для которого требуется этот делегат.

0 голосов
/ 28 июля 2011

Делегаты - это ссылочные типы, которые инкапсулируют функцию, поэтому по сути они являются указателями на функции.

Мне кажется, что вы пытаетесь создать своего рода репозиторий функций.Если все функции будут соответствовать сигнатуре Func, используйте это и не используйте универсальный класс Delegate.

В качестве альтернативы, если вы хотите хранить все различные типы делегатов с разными сигнатурами, используя класс Delegate, вам, вероятно, следует использовать метод .DynamicInvoke (), а вместо MethodInfo в качестве ключа используйте нечто более простое, например строкуили возвращаемое значение функции, или некоторая их комбинация.

Вот простой пример того, что я имею в виду с различными методами для LookUp,

class FunctionRepository : List<Delegate> // could also be a Dictionary<,>
{
    public R Invoke<R>(string name, params object[] args)
    {
        var _delegate = this.Single(x => x.Method.ReturnType == typeof(R)
            && x.Method.Name == name);

        return (R)_delegate.DynamicInvoke(args);
    }  

    public Func<R> LookUp<R>(string name, params object[] args)
    { 
        var _delegate = this.Single(x => x.Method.ReturnType == typeof(R) 
            && x.Method.Name == name);

        return () => (R)_delegate.DynamicInvoke(args); 
    }

    public Func<Object[], R> LookUp<R>(string name)
    { 
        var _delegate = this.Single(x => x.Method.ReturnType == typeof(R) 
            && x.Method.Name == name);

        return (args) => (R)_delegate.DynamicInvoke(args); 
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...