Home > database >  A C# function that returns a nullable type for any T - reference or value
A C# function that returns a nullable type for any T - reference or value

Time:12-17

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);
  •  Tags:  
  • c#
  • Related