Short version: can I define a function in C# that returns null
for any given T
type?
Right now, I essentially have to use two different functions:
private static Nullable<T> GetNullForValueType<T>() where T : struct {
return null;
}
private static T? GetNullForRefType<T>() where T : class {
return null;
}
Question: is there a way to consolidate those into one?
Long version
I have an application that loads values from a text file. I use a set of value loaders that load values of different types. I'd like to make these loaders composable, e.g. "Required" or "Nullable", or "ContainsOneOfTheseValues", etc. Here is a unit test to demonstrate:
namespace TestProject1;
public class UnitTest1 {
private static Func<string, Nullable<T>> NullableValueTypeLoader<T>(Func<string, T> innerLoader) where T : struct {
return (String text) => string.IsNullOrWhiteSpace(text) ? default(T?) : innerLoader(text);
}
private static Func<string, T?> NullableRefTypeLoader<T>(Func<string, T> innerLoader) where T : class {
return (String text) => string.IsNullOrWhiteSpace(text) ? null : innerLoader(text);
}
private string StringLoader(string text) {
return text.Trim();
}
private int IntLoader(string text) {
return int.Parse(text);
}
[Fact]
public void Test1() {
Assert.Equal(123, IntLoader("123"));
Assert.Equal("xyz", StringLoader(" xyz "));
Assert.Null(NullableValueTypeLoader(IntLoader)(""));
Assert.Null(NullableRefTypeLoader(StringLoader)(""));
}
}
Question: Is there a way to rewrite this so I can use a single Nullable
function that can handle both value and reference types?
I'm on C# 10. Can upgrade to 11 once Rider supports .net 7 better.
CodePudding user response:
can I define a function in C# that returns null for any given T type
No, they're different types.
However default
should get you there most of the way by changing your function implementations as such to be more symmetrical:
private static Func<string, T?> NullableValueTypeLoader<T>(Func<string, T> innerLoader) where T : struct =>
text => string.IsNullOrWhiteSpace(text) ? default : (T?)innerLoader(text);
private static Func<string, T?> NullableRefTypeLoader<T>(Func<string, T> innerLoader) where T : class =>
text => string.IsNullOrWhiteSpace(text) ? default : innerLoader(text);