Luk*_*keH 14
它不是标准的C#,但是,除了Lasse和Jon的答案之外,还有一些IL-fiddling你可以进行非虚拟调用(虚拟或非虚拟方法)传递null this:
using System;
using System.Reflection.Emit;
class Test
{
static void Main()
{
CallWithNullThis("Foo");
CallWithNullThis("Bar");
}
static void CallWithNullThis(string methodName)
{
var mi = typeof(Test).GetMethod(methodName);
// make Test the owner type to avoid VerificationException
var dm = new DynamicMethod("$", typeof(void), Type.EmptyTypes, typeof(Test));
var il = dm.GetILGenerator();
il.Emit(OpCodes.Ldnull);
il.Emit(OpCodes.Call, mi);
il.Emit(OpCodes.Ret);
var action = (Action)dm.CreateDelegate(typeof(Action));
action();
}
public void Foo()
{
Console.WriteLine(this == null ? "Weird" : "Normal");
}
public virtual void Bar()
{
Console.WriteLine(this == null ? "Weird" : "Normal");
}
}
Run Code Online (Sandbox Code Playgroud)
无论方法是否为虚拟,都无法在正常的C#中执行此操作(即以正常方式调用方法或属性).
对于非虚方法,您可以从开放实例方法创建委托,有效地将实例方法视为具有目标类型的第一个参数的静态方法.您可以使用null参数调用该委托,并this == null在方法中进行观察.
对于虚拟方法,您必须非虚拟地调用该方法 - 这可能发生在诸如base.Foo(...)...之类的调用中,但我不确定是否有任何方法可以使用null进行那种非虚拟调用论点.委托方法肯定不适用于此.
演示代码:
using System;
class Test
{
static void Main()
{
Action<Test> foo = (Action<Test>)
Delegate.CreateDelegate(typeof(Action<Test>), typeof(Test).GetMethod("Foo"));
foo(null); // Prints Weird
Action<Test> bar = (Action<Test>)
Delegate.CreateDelegate(typeof(Action<Test>), typeof(Test).GetMethod("Bar"));
bar(null); // Throws
}
public void Foo()
{
Console.WriteLine(this == null ? "Weird" : "Normal");
}
public virtual void Bar()
{
Console.WriteLine(this == null ? "Weird" : "Normal");
}
}
Run Code Online (Sandbox Code Playgroud)
this虚拟呼叫中无法为空.如果您有一个空引用,那么您没有对象的实例,如果您没有对象的实例,则无法获取对象的类型来确定要调用的虚拟方法.
在非虚方法中this也不能为空,但这是因为编译器不允许你进行调用,理论上可以进行调用.您可以在空引用上调用扩展方法,这将使this参数为null.
类似地,理论上可以使用空引用对虚拟方法进行非虚拟调用.指定确切的方法,并使用反射可能可以绕过编译器中的限制并使用空引用调用该方法.
| 归档时间: |
|
| 查看次数: |
1728 次 |
| 最近记录: |