Tag: 委托

提供.NET方法作为委托回调

将.NET方法作为代理回调传递给PowerShell中的.NET对象的语法是什么? 例如: C#: public class Class1 { public static void MyMethod(Action obj) { obj(“Hey!”); } } public class Class2 { public static void Callback(object obj) { Console.Writeline(obj.ToString()); } } 电源shell: [Class1]::MyMethod([Class2]::Callback) 这不起作用。

编译器为delegate关键字生成的密封类包含虚拟方法

在C#中使用delegate关键字时,C#编译器会自动生成从System.MulticastDelegate类派生的类。 此编译器生成的类还包含3个方法: Invoke, BeginInvoke and EndInvoke 。 所有这三种方法都标记为public virtual extern但有趣的是,类本身标记为sealed 。 在密封类中定义的虚拟方法不仅违反直觉,而且在C#中实际上是非法的。 所以我的问题是,是否有一个特定的原因,或者它只是其中一个无害的事情,记住一些假设的未来增强? 编辑1: 可能的原因是强制使用’callVirt’IL操作码而不是’调用’,以便在尝试执行这三种方法中的任何一种之前,CLR始终检查委托对象为空? 虽然我不明白为什么delegate在这方面应该是一个特例。 也不是强制使用callvirt的性能打击(虽然它可能是微不足道的) 编辑2: 添加了CIL标记,因为事实certificate定义委托的C#方式实际上是由CIL标准强制执行的。 标准规定(以下不是全文) 代理应具有System.Delegate的基本类型。 代表应宣布密封 ,代表的唯一成员应为此处规定的前两种或全部四种方法。 这些方法应声明为运行时和管理。 它们不应具有身体,因为该身体应由VES自动创建。 委托上可用的其他方法inheritance自基类库中的System.Delegate类。 委托方法是: 实例构造函数 Invoke方法应该是虚拟的 BeginInvoke方法(如果存在)应为虚拟方法 EndInvoke方法应该是虚拟的 所以这绝对不是编译器进程的副作用,或者类似于其他有趣的编译器输出。 如果标准强调某些东西,那必须是出于某种充分的理由和理由。 所以现在的问题是为什么代表们的CIL标准同时强调密封和虚拟? 渔获物在这里吗?: 它们不应具有身体,因为该身体应由VES自动创建。 它们是否标记为虚拟,以便在调用这些方法时可以执行VES / CLR生成的主体?

在.NET中,委托的内部实现是什么?

我理解委托人的声明是这样的: public delegate int PerformCalculation(int x, int y); 但是,必须有更多的事情发生。 委托的目的是提供指向方法的指针,为此,您将对方法的引用封装在委托中。 这个参考是什么类型的结构(代表内部)? 我也明白你可以在委托中封装对多个方法的引用。 这是否意味着委托中有一个包含这些数组的数组? 此外,委托中定义了哪些方法等。当您使用简洁声明委托时,实际发生了什么: public delegate int PerformCalculation(int x, int y); ? 编辑:一些澄清。 声明委托时,编译器会自动创建一个从System.MulticastDelegateinheritance的密封类。 如果你用ildasm查看你的程序集,你可以看到这个。 这很整洁。 基本上,使用一个语句,您将在编译时获得为您生成的全新类,并且它具有您需要的所有function。

线程和代表 – 我不完全理解他们的关系

我写了一个看起来像这样的代码: Thread t = new Thread(() => createSomething(dt, start, finish) ); t.Start(); 它工作(有时几乎感觉有多个线程) 但我不使用任何代表。 没有代表的踏板是什么意思 如果需要代表 – 那么请告诉我与代表的联系是什么以及如何。

通过放弃.NET中的标准EventHandler模​​式我会失去什么?

.NET中的事件有一个标准模式 – 它们使用一个delegate类型,它接受一个名为sender的普通对象,然后是第二个参数中的实际“payload”,它应该从EventArgs派生。 从EventArgs派生的第二个参数的基本原理似乎非常清楚(请参阅.NET Framework标准库带注释的参考 )。 它旨在确保随着软件的发展,事件接收器和源之间的二进制兼容性。 对于每个事件,即使它只有一个参数,我们派生一个自定义事件参数类,它具有包含该参数的单个属性,这样我们就可以保留在未来版本中向有效负载添加更多属性而不破坏现有客户端代码的能力。 。 在独立开发组件的生态系统中非常重要。 但我发现零参数也是如此。 这意味着如果我的第一个版本中有一个没有参数的事件,我会写: public event EventHandler Click; ……然后我做错了。 如果我将来的委托类型更改为新的类作为其有效负载: public class ClickEventArgs : EventArgs { … …我将破坏与客户的二进制兼容性。 客户端最终绑定到一个内部方法add_Click的特定重载,它接受EventHandler ,如果我更改了委托类型,那么他们就找不到那个重载,所以有一个MissingMethodException 。 好的,那么如果我使用方便的通用版本怎么办? public EventHandler Click; 不,仍然是错的,因为EventHandler不是EventHandler 。 因此,要获得EventArgs的好处,您必须从中获取,而不是直接使用它。 如果你不这样做,你也可以不使用它(在我看来)。 然后是第一个参数, sender 。 在我看来,这似乎是一个邪恶耦合的配方。 事件触发本质上是一个函数调用。 一般来说,函数是否应该能够通过堆栈挖掘并找出调用者是谁,并相应地调整其行为? 我们是否应该强制接口看起来像这样? public interface IFoo { void Bar(object caller, int actualArg1, …); } […]

为什么编译器不能在这种重载决策情况下告诉更好的转换目标? (协方差)

理解关于重载决策的C#语言规范显然很难,现在我想知道为什么这个简单的情况失败了: void Method(Func f) { } void Method(Func f) { } void Call() { Method(() => { throw new NotSupportedException(); }); } 这给出了编译时错误CS0121, 以下方法或属性之间的调用是不明确的:后面是我的两个Method函数成员(重载)。 我所期望的是Func是一个比Func 更好的转换目标 ,然后应该使用第一个重载。 自.NET 4和C#4(2010)以来,generics委托类型Func在TResult一直是协变的,因此从Func到Func存在隐式转换,而显然没有隐式转换可以从Func到Func 。 那么它会使Func成为更好的转换目标,而重载决策应该选择第一次重载? 我的问题很简单:我在这里错过了C#规范的哪一部分? 增加:这很好用: void Call() { Method(null); // OK! }

我可以使用lambda语法忽略委托参数吗?

我很好奇为什么C#允许我在某些情况下忽略委托参数而不是其他情况。 例如,这是允许的: Action action = delegate { Console.WriteLine(“delegate”); }; 但这不是: Action action = () => Console.WriteLine(“lambda”); 有没有办法初始化委托并使用lambda忽略参数? 我知道我可以向lambda添加一个参数并修复前一行,但这更像是一个与编译器有关的学术问题,以及为什么或如何工作。

C#代理是否是线程安全的?

如果你有一个带有委托成员变量的类实例,并且多个线程调用该委托(假设它指向一个长期运行的方法),是否存在任何争用问题? 你是否需要锁定委托,或者每个线程调用委托所指向的方法是否安全,因为每个线程都有自己的调用堆栈?

有没有办法创建一个委托来获取和设置FieldInfo的值?

对于属性,有GetGetMethod和GetSetMethod以便我可以这样做: Getter = (Func)Delegate.CreateDelegate(typeof(Func), propertyInfo.GetGetMethod()); 和 Setter = (Action)Delegate.CreateDelegate(typeof(Action), propertyInfo.GetSetMethod()); 但是我该如何处理FieldInfo ? 我不是在寻找GetValue和SetValue代表(这意味着我每次都会调用reflection) Getter = s => (T)fieldInfo.GetValue(s); Setter = (s, t) => (T)fieldInfo.SetValue(s, t); 但是如果这里有CreateDelegate方法吗? 我的意思是, 因为赋值返回一个值 ,我可以将赋值视为一种方法吗? 如果有的话,它有一个MethodInfo句柄吗? 换句话说,我如何传递正确的MethodInfo设置并从成员字段获取值到CreateDelegate方法,以便我得到一个委托,我可以直接读取和写入字段? Getter = (Func)Delegate.CreateDelegate(typeof(Func), fieldInfo.??); Setter = (Action)Delegate.CreateDelegate(typeof(Action), fieldInfo.??); 我可以构建表达式并编译它,但我正在寻找更简单的东西。 最后,如果问题没有答案,我不介意去表达路线 ,如下所示: var instExp = Expression.Parameter(typeof(S)); var fieldExp = Expression.Field(instExp, fieldInfo); Getter = Expression.Lambda<Func>(fieldExp, instExp).Compile(); […]

Delegate.CreateDelegate与DynamicMethod vs Expression

关于使反思飞行和探索代表的问题 …… 如果我需要为动态加载类型的方法创建委托Func ,我可能会使用(1) Delegate.CreateDelegate (2) DynamicMethod (3) Expression树。 让我们说一组动态加载的类型/方法在应用程序启动时通过config反映一次,并在应用程序的整个生命周期中使用(启动性能不是问题,也不是内存),代理被缓存并分派到一个强烈的方式。 这些代理是同时访问的热路径。 您更喜欢哪种动态绑定方法?为什么?