将可能为Null Reference Exception的函数作为参数传递

时间:2014-02-21 02:18:14

标签: c#

我想编写一个辅助方法,它接受一个func和一个第二个参数T,然后尝试调用它。如果出现Null Reference Exception,则返回T(第二个参数)。如果成功,则返回传入的func的结果。所以代替:

tableRow[rowNum, fieldNamePos].Value != null ? tableRow[rowNum, fieldNamePos].Value.ToString() : "";

我可以写

Helper.GetDefaultIfNull(tableRow[rowNum, fieldNamePos].Value.ToString,"")

我相信它更简洁,代码更少。这是我在GetDefaultIfNull方法中的内容:

public T GetDefaultIfNull<T>(Func<T> funcToInvoke, T defaultValue)
{
    T result;
    try
    {
       result = stringFunc.Invoke();
    }
    catch (NullReferenceException)
    {
       result = defaultValue;
    }

    return result;
}

当我运行测试时,这在传入非空引用时正常工作,但是当传入空引用时,它会在调用方法时抛出错误,因此它似乎在将函数传递给方法时调用该函数?这是测试代码:

[TestMethod]
    public void NULL_EXCEPTION_return_default()
    {
        StringBuilder sb = null;

        //Func<string> stringFunc = ; 
        var defaultValue = "";
        var result = new Helper().GetDefaultIfNull(sb.ToString, defaultValue);

        Assert.AreEqual(defaultValue, result);
    }

有办法做到这一点吗?

4 个答案:

答案 0 :(得分:3)

这种情况正在发生,因为通过这种方式在对象上访问一个方法,你仍然取消引用空指针。换句话说,这一行:

sb.ToString

正在尝试访问空引用(ToString)的成员(sb)。

更改调用函数的方式可以解决问题:

var result = new Helper().GetDefaultIfNull(() => sb.ToString(), defaultValue);

也就是说,创建一个新的Lambda并调用它。你方法中预期的NullReferenceException将以你期望的方式被抛出,捕捉和处理。

答案 1 :(得分:0)

尝试查找函数时发生空引用,即如果sb为空,则sb.ToString将抛出NullReferenceException。我建议您可能想要做类似

的事情
public T GetDefaultIfNull<T>(object value, T defaultValue)
{
     return value == null 
             ? defaultValue
             : Convert.ChangeType(value, typeof(T));
}

然后将其称为

Helper.GetDefaultIfNull(tableRow[rowNum, fieldNamePos].Value, "");

现在,假设该值可以转换为T,但我假设你知道它应该是什么类型,转换操作要么是无操作,要么你知道它会工作

答案 2 :(得分:0)

尝试一下:

public T GetDefaultIfNull<T>(Func<T> funcToInvoke, T defaultValue)
{
    T result;
    try
    {
        result = stringFunc.Invoke();
        if (result == null)
        {
             //Do something with result as it is not null
        }
        else{
            result = defaultValue;
        }
    }
    catch (Exception ex)
    {
        ex.Message;
    }

    return result;
}

答案 3 :(得分:0)

您还可以选择进行简单的完整性检查

public T GetDefaultIfNull<T>(Func<T> funcToInvoke, T defaultValue) {
    T result;
    if (funcToInvoke == null) {
        return result = defaultValue;
    }
    try {
        result = funcToInvoke.Invoke();
    } catch (Exception) {
        result = defaultValue;
    }

    return result;
}

测试方法如下。

//running a NUnit test
[Test]
public void NULL_EXCEPTION_return_default() {
    StringBuilder sb = null;
    var defaultValue = string.Empty;
    var result = new TestHelper().GetDefaultIfNull(sb.ToString, defaultValue);

    Assert.AreEqual(defaultValue, result);
}
相关问题