3

假设我有一个声明如下的类:

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”分配一个值非常方便。

我只是使用了不正确的语法吗?有没有更好的方法来创建一个类并在一行中分配一个动作?我应该直接管理并管理一个巨大的 switch 语句吗?

4

3 回答 3

3

您必须创建类的实例,然后将属性设置为实例成员。就像是:

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不是静态方法,你不能用类名访问它。

于 2012-12-21T06:03:16.893 回答
2

在对象初始化器语法中,您无法在明确分配之前访问正在初始化的变量:

ExampleClass excl = new ExampleClass() 
{ 
    Do = excl.FuncA //excl is unavailable here
}

阅读Object and Collection Initializers (C# Programming Guide)了解更多信息。


例如,您可以执行以下操作:

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 };
于 2012-12-21T06:03:50.527 回答
0

如果您有扩展方法,请确保在调用扩展方法或处理扩展方法中的空值之前这些值不为空。

例如

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
    {

    }
}

如果您拥有扩展类,要处理这种情况,请处理空值并断言空值。

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())
    {

    }
}
于 2017-05-04T11:18:04.497 回答