Это работает (в C # 4.0 по крайней мере - не пробовали в более ранних версиях):
SomeDelegate a = Inc;
Func<int, int> c = new Func<int, int>(a);
Если вы посмотрите на IL, это скомпилируется в тот же код, что и ответ Winston. Вот IL для второй строки того, что я только что написал:
ldloc.0
ldftn instance int32 ConsoleApplication1.Program/SomeDelegate::Invoke(int32)
newobj instance void class [mscorlib]System.Func`2<int32,int32>::.ctor(object, native int)
И это также то, что вы видите, если назначить a.Invoke
на c
.
Кстати, хотя решение Диего более эффективно, поскольку полученный делегат ссылается непосредственно на базовый метод, а не на другой делегат, он не обрабатывает делегатов многоадресной рассылки правильно. Решение Winston делает это, потому что оно просто полностью подчиняется другому делегату. Если вам нужно прямое решение, которое также обрабатывает делегатов с несколькими целями, вам нужно что-то более сложное:
public static TResult DuplicateDelegateAs<TResult>(MulticastDelegate source)
{
Delegate result = null;
foreach (Delegate sourceItem in source.GetInvocationList())
{
var copy = Delegate.CreateDelegate(
typeof(TResult), sourceItem.Target, sourceItem.Method);
result = Delegate.Combine(result, copy);
}
return (TResult) (object) result;
}
Это делает правильную вещь для делегатов с одной целью, кстати, - это закончится создавая только один делегат целевого типа, который ссылается непосредственно на любой метод (и, где это применимо, объект), на который ссылается входной делегат.