我创建了将属性lambda转换为委托的方法:
public static Delegate MakeGetter<T>(Expression<Func<T>> propertyLambda)
{
var result = Expression.Lambda(propertyLambda.Body).Compile();
return result;
}
public static Delegate MakeSetter<T>(Expression<Action<T>> propertyLambda)
{
var result = Expression.Lambda(propertyLambda.Body).Compile();
return result;
}
Run Code Online (Sandbox Code Playgroud)
这些工作:
Delegate getter = MakeGetter(() => SomeClass.SomeProperty);
object o = getter.DynamicInvoke();
Delegate getter = MakeGetter(() => someObject.SomeProperty);
object o = getter.DynamicInvoke();
Run Code Online (Sandbox Code Playgroud)
但这些不会编译:
Delegate setter = MakeSetter(() => SomeClass.SomeProperty);
setter.DynamicInvoke(new object[]{propValue});
Delegate setter = MakeSetter(() => someObject.SomeProperty);
setter.DynamicInvoke(new object[]{propValue});
Run Code Online (Sandbox Code Playgroud)
MakeSetter行失败,"无法根据用法推断出类型参数.请尝试明确指定类型参数."
我正在尝试做什么?提前致谢.
我在这做错了什么?我该如何执行我的行动?
var recurse = new Action<IItem, Int32>((item, depth) =>
{
if (item.Items.Count() > 0) recurse(item, depth + 1); // red squiggly here
// ...
});
Run Code Online (Sandbox Code Playgroud)
当打电话recurse说"方法,代表或事件预期"时,我得到了一个红色的波浪形.
更新
我接受了Homam的回答.我只是想添加/分享同样的另一种语法......但是我觉得眼睛看起来更容易......
Action<IEnumerable<Item>> Recurse = null;
Recurse = item =>
{
if (item.Items != null) Recurse(item.Items);
// ...
};
Run Code Online (Sandbox Code Playgroud) C#4.0协同和逆变支持的一些奇怪行为:
using System;
class Program {
static void Foo(object x) { }
static void Main() {
Action<string> action = _ => { };
// C# 3.5 supports static co- and contravariant method groups
// conversions to delegates types, so this is perfectly legal:
action += Foo;
// since C# 4.0 much better supports co- and contravariance
// for interfaces and delegates, this is should be legal too:
action += new Action<object>(Foo);
}
}
Run Code Online (Sandbox Code Playgroud)
这是结果 ArgumentException: Delegates must be of the …
我正在尝试使用:
$('mydiv').delegate('hover', function() {
$('seconddiv').show();
}, function() {
//For some reason jQuery won't run this line of code
$('seconddiv').hide();
});
Run Code Online (Sandbox Code Playgroud) 关于接受的答案的快速说明:我不同意Jeffrey的一小部分答案,即Delegate必须是一个引用类型,因此所有代表都是引用类型.(多层继承链排除值类型并不是真的;例如,所有枚举类型都System.Enum继承自System.ValueType,而继承自所有引用类型的继承System.Object,但是我认为事实是从根本上说,所有代表事实上都不仅仅是继承而是来自这里的关键实现.正如雷蒙指出,在一个评论他的答案,一旦你承诺支持多用户,有真的没有一点不使用引用类型的代表本身,因为需要一个数组的地方.DelegateMulticastDelegate
请参阅底部的更新.
如果我这样做,我一直觉得很奇怪:
Action foo = obj.Foo;
Run Code Online (Sandbox Code Playgroud)
我每次都在创建一个新 Action对象.我确信成本很低,但它涉及到内存分配以便以后进行垃圾回收.
鉴于委托本身就是不可变的,我想知道为什么它们不能成为价值类型?然后像上面那样的一行代码只会对堆栈上的内存地址进行简单的赋值*.
即使考虑匿名功能,似乎(对我而言)这也行得通.请考虑以下简单示例.
Action foo = () => { obj.Foo(); };
Run Code Online (Sandbox Code Playgroud)
在这种情况下foo确实构成了一个闭包,是的.在许多情况下,我想这确实需要一个实际的引用类型(例如当局部变量被关闭并在闭包内被修改时).但在某些情况下,它不应该.例如,在上面的例子中,似乎支持闭包的类型看起来像这样: 我收回了我对此的原始观点.下面确实需要一个引用类型(或:它并不需要是的,但如果它是一个struct只是要它来获得反正盒装).所以,忽略下面的代码示例.我留下它只是为了提供具体提及它的答案的背景.
struct CompilerGenerated
{
Obj obj;
public CompilerGenerated(Obj obj)
{
this.obj = obj;
}
public void CallFoo()
{
obj.Foo();
}
}
// …Run Code Online (Sandbox Code Playgroud) 我确信我只是不了解C#中事件和/或委托的基本内容,但为什么我不能在此代码示例中进行布尔测试:
public class UseSomeEventBase {
public delegate void SomeEventHandler(object sender, EventArgs e);
public event SomeEventHandler SomeEvent;
protected void OnSomeEvent(EventArgs e) {
// CANONICAL WAY TO TEST EVENT. OF COURSE, THIS WORKS.
if (SomeEvent != null) SomeEvent(this, e);
}
}
public class UseSomeEvent : UseSomeEventBase {
public bool IsSomeEventHandlerNull() {
// "LEFT HAND SIDE" COMPILER ERROR
return SomeEvent == null;
}
}
class Program {
static void Main(string[] args) {
var useSomeEvent = new UseSomeEvent();
useSomeEvent.SomeEvent +=new UseSomeEventBase.SomeEventHandler(FuncToHandle);
// "LEFT HAND …Run Code Online (Sandbox Code Playgroud) 我有一个带out参数的方法,我想指出一个Action或Func(或其他类型的委托).
这很好用:
static void Func(int a, int b) { }
Action<int,int> action = Func;
Run Code Online (Sandbox Code Playgroud)
但事实并非如此
static void OutFunc(out int a, out int b) { a = b = 0; }
Action<out int, out int> action = OutFunc; // loads of compile errors
Run Code Online (Sandbox Code Playgroud)
这可能是重复的,但搜索'out参数'并不是特别富有成效.
让我提前道歉 - 我可能正在屠杀术语.我对闭包是什么有一个模糊的理解,但无法解释我所看到的行为.至少,我认为这是一个封闭问题.我在线搜索,但没有找到合适的关键字来获得我想要的东西.
具体来说 - 我有两个非常相似的代码块(至少在我看来).第一:
static void Main(string[] args)
{
Action x1 = GetWorker(0);
Action x2 = GetWorker(1);
}
static Action GetWorker(int k)
{
int count = 0;
// Each Action delegate has it's own 'captured' count variable
return k == 0 ? (Action)(() => Console.WriteLine("Working 1 - {0}",count++))
: (Action)(() => Console.WriteLine("Working 2 - {0}",count++));
}
Run Code Online (Sandbox Code Playgroud)
如果运行此代码并调用x1()和x2(),您将看到它们保持单独的"count"值.
foreach(var i in Enumerable.Range(0,4))
{
x1(); x2();
}
Run Code Online (Sandbox Code Playgroud)
输出:
Working 1 - 0
Working 2 - 0
Working 1 - 1 …Run Code Online (Sandbox Code Playgroud) 我有一个下拉列表,通过检查类的方法并包括与特定签名匹配的方法来填充.问题在于从列表中获取所选项目并让委托在类中调用该方法.第一种方法有效,但我无法弄清楚第二种方法的一部分.
例如,
public delegate void MyDelegate(MyState state);
public static MyDelegate GetMyDelegateFromString(string methodName)
{
switch (methodName)
{
case "CallMethodOne":
return MyFunctionsClass.CallMethodOne;
case "CallMethodTwo":
return MyFunctionsClass.CallMethodTwo;
default:
return MyFunctionsClass.CallMethodOne;
}
}
public static MyDelegate GetMyDelegateFromStringReflection(string methodName)
{
MyDelegate function = MyFunctionsClass.CallMethodOne;
Type inf = typeof(MyFunctionsClass);
foreach (var method in inf.GetMethods())
{
if (method.Name == methodName)
{
//function = method;
//how do I get the function to call?
}
}
return function;
}
Run Code Online (Sandbox Code Playgroud)
如何使第二种方法的注释部分工作?我如何MethodInfo投入代表?
谢谢!
编辑:这是工作解决方案.
public static MyDelegate GetMyDelegateFromStringReflection(string methodName) …Run Code Online (Sandbox Code Playgroud) 我不能成为唯一一个厌倦了定义和命名委托只需要一个需要委托的东西的人.例如,我想从可能的其他线程调用表单中的.Refresh(),所以我编写了这段代码:
private void RefreshForm()
{
if (InvokeRequired)
Invoke(new InvokeDelegate(Refresh));
else
Refresh();
}
Run Code Online (Sandbox Code Playgroud)
我甚至不确定我必须这样做,我只是读得足以害怕它在以后的某个阶段不起作用.
InvokeDelegate实际上是在另一个文件中声明的,但是我真的需要一个专门用于此的整个委托吗?根本没有任何通用代表?
我的意思是,例如,有一个Pen类,但也有Pens.选择笔,所以你不必重拍整个事情.它不一样,但我希望你理解我的意思.
delegates ×10
c# ×9
.net ×2
.net-4.0 ×1
closures ×1
covariance ×1
events ×1
handler ×1
jquery ×1
lambda ×1
properties ×1
recursion ×1
reflection ×1
value-type ×1