Большое время вычислений - PullRequest
2 голосов
/ 12 октября 2011

Вот ссылка на мой предыдущий вопрос, который привел меня к этому. C # Оптимизация вложенного цикла foreach

Время вычислений все еще велико, и я не уверен, в чем причина.

object foo;
List<string> StringList = new List<string>(); // Populated by previous code
Dictionary<string, Type> assemblyTypes = RandomAssembly.GetTypes().ToDictionary(t => t.Name, t => t);

  foreach (String name in StringList)
  {                     
    if (assemblyTypes.ContainsKey(name))
    {
      // Create an instance of the matching class and add it
      // to the appropriate lists.
      Type at = assemblyTypes[name];
      foo = Activator.CreateInstance(at);       
      ArbitraryList1.Add(foo);
    }
  }    

Ответы [ 3 ]

3 голосов
/ 12 октября 2011

Если время вычислений заметно медленное, я полагаю, вы часто обращаетесь к этому коду и обновляете множество объектов, о которых вы мало что знаете во время компиляции.

Вместо того, чтобы хранить классы в Dictionary<string, type> и вызывать CreateInstance, вы хотите сохранить словарь их конструкторов Dictionary<string, ConstructorInfo>, чтобы вы могли вызывать их напрямую, без необходимости каждый раз искать их с отражением.

Таким образом, вы можете просто вызвать AssemblyConstructors [Name] .Invoke (), чтобы создать новый экземпляр класса.

Таким образом, вам нужно использовать отражение один раз, чтобы найти конструкторы.

// keep a dictionary of constructors (instead of the types)
var Constructors = new Dictionary<string, ConstructorInfo>();            

// add this class to this dictionary
Type t = typeof(SomeClass);            
string name = t.Name;
Constructors[name] = t.GetConstructors()[0]; // use reflection only once here, afterwards we reuse the reflected info

// new up an instance 
var o = Constructors[name].Invoke(new object[] {}); 

Я думаю, что первый конструктор будет без параметров. Еще попробуйте что-то вроде t.GetConstructors().Where(x => x.GetParameters().Count() == 0).First(); Это самый простой способ, который я знаю, потому что, очевидно, вы не можете получить делегата для конструктора .

Если вы пишете классы, которые вы обновляете сами, у вас может быть общий базовый класс или интерфейс с методом, который его создает, и таким образом вы можете сохранить делегат для этого конструктора, что еще быстрее.

В этом посте также есть некоторые интересные идеи, которые продвигают оптимизацию намного . Если вы хотите сделать это быстро, вы можете. Почти так же быстро, как просто позвонить new KnownClass()

Удачи,

GJ

1 голос
/ 12 октября 2011

Резюме: практически неограниченный цикл с одной из самых медленных функций в структуре, вызываемой на каждой итерации, будет медленным.

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

0 голосов
/ 12 октября 2011

Используйте Dictionary.TryGetValue , чтобы найти ключ «имя» один раз вместо двух.Это всего лишь небольшой совет, так как я уверен, что отражение - это узкое место.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...