实例方法的委托不能为null 'this'
本文关键字:this null 不能 实例方法 | 更新日期: 2023-09-27 17:49:20
假设我有一个类声明如下:
public class ExampleClass
{
public Action<int> Do { get; set; }
public ExampleClass()
{
}
public void FuncA(int n)
{
//irrelevant code here
}
public void FuncB(int n)
{
//other irrelevant code here
}
}
我希望能够像这样使用这个类
ExampleClass excl = new ExampleClass() { Do = FuncA }
或
ExampleClass excl = new ExampleClass() { Do = excl.FuncA }
或
ExampleClass excl = new ExampleClass() { Do = ExampleClass.FuncA }
我可以在那里编译第二个选项,但是当我点击该代码时,我得到一个"Delegate to an instance method cannot have null 'this'."
异常。第三个甚至没有意义,因为FuncA不是静态的。
在我的实际代码中,它可能绑定到10-15个不同的函数,我可以随时添加或删除它们,所以我不想有一个大的switch或it-else语句。此外,能够在实例化类时为"Do"赋值是非常方便的。
我只是使用了错误的语法吗?有没有更好的方法来创建一个类并在一行中分配一个动作?我应该像个男人一样处理一个巨大的开关声明吗?
您必须创建类的实例,然后将属性设置为实例成员。比如:
ExampleClass excl = new ExampleClass();
excl.Do = excl.FuncA;
你的台词:
ExampleClass excl = new ExampleClass() { Do = FuncA }
如果没有类的实例,FuncA是不可见的。
为:ExampleClass excl = new ExampleClass() { Do = excl.FuncA }
实例还没有被创建,这就是为什么你得到空引用的异常。
为:ExampleClass excl = new ExampleClass() { Do = ExampleClass.FuncA }
FuncA
不是静态方法,您不能使用类名访问它。
在对象初始化语法中,在确定赋值之前不能访问被初始化的变量:
ExampleClass excl = new ExampleClass()
{
Do = excl.FuncA //excl is unavailable here
}
阅读对象和集合初始化器(c#编程指南)获取更多信息。
你可以这样做,例如:
public class ExampleClass
{
public Action<int> Do { get; set; }
public ExampleClass(bool useA)
{
if (useA)
Do = FuncA;
else
Do = FuncB;
}
public void FuncA(int n)
{
//irrelevant code here
}
public void FuncB(int n)
{
//other irrelevant code here
}
}
并使用:
ExampleClass exclA = new ExampleClass(true);
ExampleClass exclB = new ExampleClass(false);
另一个想法是,如果这些函数可以声明为static
(即它们不需要ExampleClass
的任何实例成员),那么这将工作:
public class ExampleClass
{
public Action<int> Do { get; set; }
public ExampleClass() { }
public static void FuncA(int n) { /*...*/}
public static void FuncB(int n) { /*...*/}
}
和你想要的方式使用它:
ExampleClass excl = new ExampleClass() { Do = ExampleClass.FuncA };
如果您有扩展方法,请确保在调用扩展方法或在扩展方法中处理null之前这些值不是null。
例如
public static ExtensionClass
{
public static bool RunExtensionMethod(this object myObject)
{
var someExecutionOnMyObject = myObject.IsValid();
//the above line would invoke the exception when myObject is null
return someExecutionOnMyObject ;
}
}
public void CallingMethod()
{
var myObject = getMyObject();
if(myObject.RunExtensionMethod()) //This would cause "delete to an instance method cannot have null" if myObject is null
{
}
}
要处理此场景,如果您拥有扩展类,则处理null并断言null。
public static ExtensionClass
{
public static bool RunExtensionMethod(this object myObject)
{
if(myObject == null) throw new ArgumentNullException(nameof(myObject));
var someExecutionOnMyObject = myObject.IsValid();
return someExecutionOnMyObject ;
}
}
public void CallingMethod()
{
var myObject = getMyObject();
if(myObject != null && myObject.RunExtensionMethod())
{
}
}