Reputation: 539
I'd like to write a helper method that takes a func and a second parameter T, and attempts to invoke it. If a Null Reference Exception occurs, return T (second parameter). If it's successful, return the result of the func passed in. So instead of:
tableRow[rowNum, fieldNamePos].Value != null ? tableRow[rowNum, fieldNamePos].Value.ToString() : "";
I could write
Helper.GetDefaultIfNull(tableRow[rowNum, fieldNamePos].Value.ToString,"")
Which I believe is more concise and less code. Here's what I have in the GetDefaultIfNull method:
public T GetDefaultIfNull<T>(Func<T> funcToInvoke, T defaultValue)
{
T result;
try
{
result = stringFunc.Invoke();
}
catch (NullReferenceException)
{
result = defaultValue;
}
return result;
}
When I run tests, this works correctly when passing in a non null reference, however when passing in a null reference, it throws an error when calling the method so it seems to be invoking the function while passing it into the method? Here is the test code:
[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);
}
Is there a way to do this?
Upvotes: 1
Views: 1746
Reputation: 126042
This is happening because by accessing a method this way on an object you're still dereferencing a null pointer. In other words, this line:
sb.ToString
is attempting to access a member (ToString
) of a null reference (sb
).
Changing the way you're calling your function would fix the problem:
var result = new Helper().GetDefaultIfNull(() => sb.ToString(), defaultValue);
That is, create a new Lambda and invoke that instead. The NullReferenceException
you're expecting in your method will be thrown, caught, and handled the way you expect.
Upvotes: 3
Reputation: 1708
You can also have an alternative where you do a simple sanity check
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;
}
And the test method is below.
//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);
}
Upvotes: 0
Reputation: 216
Give this a try:
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;
}
Upvotes: 0
Reputation: 532455
The null reference is occurring when attempting to find the function, i.e, if sb
is null then sb.ToString
will throw a NullReferenceException
. I would suggest that you might want to do something like
public T GetDefaultIfNull<T>(object value, T defaultValue)
{
return value == null
? defaultValue
: Convert.ChangeType(value, typeof(T));
}
Then call it as
Helper.GetDefaultIfNull(tableRow[rowNum, fieldNamePos].Value, "");
Now, this assumes that the value is convertible to T
but I'm assuming that you know what type it should be and the conversion operation would either be a no-op or you'd know that it will work.
Upvotes: 0