Нет, это невозможно. Почему бы просто не сделать это:
#define replace_to replacement here
Вы можете взломать бросок, используя трюк, в котором вы используете эквивалент c # для объединения c ++. Сложная часть - это структура с двумя членами, которые имеют [FieldOffset (0)]:
[TestFixture]
public class Demo
{
public void print(int i)
{
Console.WriteLine("Int: "+i);
}
private delegate void mydelegate(int i);
[StructLayout(LayoutKind.Explicit)]
struct funky
{
[FieldOffset(0)]
public mydelegate a;
[FieldOffset(0)]
public System.Action<int> b;
}
[Test]
public void delegatetest()
{
System.Action<int> f = print;
funky myfunky;
myfunky.a = null;
myfunky.b = f;
mydelegate a = myfunky.a;
a(5);
}
}
SomeDelegate a = Inc;
Func<int, int> b = Inc;
не подходит для
SomeDelegate a = new SomeDelegate(Inc); // no cast here
Func<int, int> b = new Func<int, int>(Inc);
Вы не можете использовать экземпляр SomeDelegate для функции Func & lt; int, int & gt; по той же причине вы не можете передать строку в словарь & lt; int, int & gt; - они разные.
Это работает:
Func<int, int> c = x => a(x);
, который является синтаксическим сахаром для
class MyLambda
{
SomeDelegate a;
public MyLambda(SomeDelegate a) { this.a = a; }
public int Invoke(int x) { return this.a(x); }
}
Func<int, int> c = new Func<int, int>(new MyLambda(a).Invoke);
public Foo
должно быть public MyLambda
?
– Chris
23 June 2014 в 13:29
Попробуйте следующее:
Func<int, int> c = (Func<int, int>)Delegate.CreateDelegate(typeof(Func<int, int>),
b.Target,
b.Method);
Func<int, int> c = b.Invoke;
. Но есть одна вещь, которую нужно помнить: в .NET все типы делегатов являются «многоадресными». делегаты, и приведенный выше код будет использовать только метод last в списке вызовов. Если вы не можете гарантировать, что в списке вызовов есть только один член, вам придется перебирать его, я думаю.
– Jeppe Stig Nielsen
6 November 2012 в 00:38
Func
имеет смысл. Какую возвращаемую стоимость вы бы использовали?
– Diego Mijelshon
6 November 2012 в 18:32
void
, например EventHandler
делегатами со многими подписчиками. Но попробуйте это: Func<int> a = () => 10; Func<int> b = () => 20; Func<int> c = () => 30; var multi = a + b + c; int answer = multi();
Это законно в языке и структуре, поэтому вы должны убедиться, что никто не использовал его.
– Jeppe Stig Nielsen
6 November 2012 в 18:42
Проблема в том, что:
SomeDelegate a = Inc;
На самом деле это не актерский состав. Это короткая форма:
SomeDelegate a = new SomeDelegate(Inc);
Поэтому нет отличных результатов. Простым решением вашей проблемы может быть это (в C # 3.0)
Func<int,int> f = i=>a(i);
Это работает (в 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;
}
Это делает правильную вещь для делегатов с одной целью, кстати, - это закончится создавая только один делегат целевого типа, который ссылается непосредственно на любой метод (и, где это применимо, объект), на который ссылается входной делегат.
Method
и Target
делегата с несколькими вызовами указывают на одну из своих целей. Я бы подумал, что было бы разумнее, чтобы точка Target
делегата была самой, и Method
указывают на свой метод Invoke
[который будет проверять, вызывал ли он себя, и если да, используйте многоадресную рассылку список] или "вызывать многоадресную рассылку" метод. Это позволило бы избежать риска случайного превращения делегата с несколькими вызовами в одноразовый вызов.
– supercat
22 January 2013 в 23:31
MulticastDelegate
является беспорядком, потому что Microsoft изменила свое мнение о том, как справиться с этим довольно поздно в тот же день. В первом публичном просмотре .NET некоторые делегаты были многоадресными, а некоторые - нет. В конце концов они решили отказаться от этого различия, но на самом деле не успели очистить вещи, что оставило несколько аномалий в иерархии типов делегатов.
– Ian Griffiths
20 February 2013 в 11:03
Это та же проблема:
public delegate int SomeDelegate1(int p);
public delegate int SomeDelegate2(int p);
...
SomeDelegate1 a = new SomeDelegate1(Inc);
SomeDelegate2 b = (SomeDelegate2)a; // CS0030
, которая является такой же проблемой, как:
public class A { int prop { get; set; } }
public class B { int prop { get; set; } }
...
A obja = new A();
B objb = (B)obja; // CS0029
Объекты не могут быть выбраны из одного типа в несвязанный другой тип, даже если типы в противном случае полностью совместимы. Из-за отсутствия лучшего термина: объект имеет идентификатор типа, который он переносит во время выполнения. Эта идентичность не может быть изменена после создания объекта. Видимым проявлением этого тождества является Object.GetType ().
Мне нравятся примеры. Вот мой пример кода:
class Program
{
class A
{
public A(D d) { d.Invoke("I'm A!"); }
public delegate string D(string s);
}
class B
{
public delegate string D(string s);
}
static void Main(string[] args)
{
//1. Func to delegates
string F(dynamic s) { Console.WriteLine(s); return s; }
Func<string, string> f = F;
//new A(f);//Error CS1503 Argument 1: cannot convert from 'System.Func<string, string>' to 'ConsoleApp3.Program.A.D'
new A(new A.D(f));//I'm A!
new A(x=>f(x));//I'm A!
Func<string, string> f2 = s => { Console.WriteLine(s); return s; };
//new A(f2);//Same as A(f)
new A(new A.D(f2));//I'm A!
new A(x => f2(x));//I'm A!
//You can even convert between delegate types
new A(new A.D(new B.D(f)));//I'm A!
//2. delegate to F
A.D d = s => { Console.WriteLine(s); return s; };
Func<string, string> f3 = d.Invoke;
f3("I'm f3!");//I'm f3!
Func<string, string> f4 = new Func<string, string>(d);
f4("I'm f4!");//I'm f4!
Console.ReadLine();
}
}
Выход:
Существует гораздо более простой способ сделать это, о чем пропустили все остальные ответы:
Func<int, int> c = a.Invoke;
Подробнее см. в в этом сообщении в блоге .
a.Invoke
, кажется, отписался нормально? gist.github.com/dtchepak/7799703
– David Tchepak
5 December 2013 в 05:33
public Foo
должно бытьpublic MyLambda
? – Chris 23 June 2014 в 13:29