Можно ли создать делегат метода экземпляра, не указывая экземпляр во время создания? Другими словами, можете ли вы создать «статический» делегат, который принимает в качестве первого параметра экземпляр, для которого должен быть вызван метод?
Например, как я могу создать следующий делегат, используя отражение?
Func<int, string> = i=>i.ToString();
Я знаю, что могу использовать methodInfo.Invoke, но это медленнее и не проверяет правильность типа, пока не будет вызвано.
Когда у вас есть MethodInfo
определенного статического метода, можно создать делегат с помощью Delegate.CreateDelegate(delegateType, methodInfo)
, и все параметры статического метода останутся свободными.
Как указал Джон Скит, вы можете просто применить то же самое, чтобы сделать открытый делегат метода экземпляра, если метод не является виртуальным для ссылочного типа. Решить, какой метод вызывать для виртуального метода, сложно, так что это не так уж и тривиально, а типы значений выглядят так, как будто они вообще не работают.
Для типов значений CreateDelegate
ведет себя очень странно:
var func37 = (Func<CultureInfo,string>)(37.ToString);
var toStringMethod = typeof(int).GetMethod("ToString", BindingFlags.Instance | BindingFlags.Public, null, new Type[] {typeof(CultureInfo) }, null);
var func42 = (Func<CultureInfo,string>)Delegate.CreateDelegate(typeof(Func<CultureInfo,string>), 42, toStringMethod,true);
Console.WriteLine( object.ReferenceEquals(func37.Method,func42.Method)); //true
Console.WriteLine(func37.Target);//37
Console.WriteLine(func42.Target);//42
Console.WriteLine(func37(CultureInfo.InvariantCulture));//37
Console.WriteLine(func42(CultureInfo.InvariantCulture));//-201040128... WTF?
Вызов CreateDelegate
с null
в качестве целевого объекта вызывает исключение привязки, если метод экземпляра принадлежит типу значения (это работает для ссылочных типов).
Несколько лет спустя: Неправильно привязанная цель, из-за которой func42(CultureInfo.InvariantCulture);
возвращала "-201040128"
вместо "42"
в моем примере, заключалась в повреждении памяти, которое могло сделать возможным удаленное выполнение кода (cve-2010-1898); это было исправлено в 2010 году в ms10-060 а> обновление безопасности. Текущие фреймворки правильно печатают 42! Это не облегчает ответ на этот вопрос, но объясняет особенно странное поведение в примере.
ref
изменений в C# 7 помогут, но я не уверен. Возможно, лучше задать новый вопрос с вашим конкретным примером и тем, что вы пробовали. 24.09.2019Test
. 25.09.2019