4

I have a function:

public static object? ToType(Type type, object? value)

I want to create a helpful shortcut like:

public static T ToType<T>(object? value)
{
  return (T)ToType(typeof(T), value);
}

C# 8.0 compiler with nullable checks enabled gives the following warning:

CS8601: Possible null reference assignment.

Function accepts string, int and other types, so I cannot set a generic constraint like class. Also, it can return null. Using T? for casting and return gives a compiler error.

Is there a way to fix the warning?

Jeremy Caney
  • 7,102
  • 69
  • 48
  • 77
  • `return ToType(typeof(T), value) as T;` ? or you can use pragma or attrbute to surpress warnings – Eldar Dec 05 '19 at 16:22
  • 3
    Well, if you pass an `int` as `T` and a value of `null` it'll throw an Exception - because you can't cast null as int (same applies for other types such as booleans etc). What would you want to happen in this instance? I'd suggest perhaps having two separate methods or put in checks for non-nullable types and return default for non-nullables? [I've answered something similar here if you want to have a look](https://stackoverflow.com/questions/59111868/why-cant-i-cast-generic-type-with-null/59111995#59111995). – Adrian Dec 05 '19 at 16:23
  • @Eldar I'd probably not mask such warning. This warning is actually something that should be fixed before code touches the production environment. – Adrian Dec 05 '19 at 16:30
  • What if `T` were substituted with `string`? The caller would get a bad surprise. You should consider returning `[MaybeNull]T` instead, then suppress the warning within the body of the method (the compiler doesn't yet do that automatically when `[MaybeNull]T` is returned. – Julien Couvreur Dec 05 '19 at 16:41
  • "as T" does not even compile because it gives "Error CS0413 The type parameter 'T' cannot be used with the 'as' operator because it does not have a class type constraint nor a 'class' constraint". I do not want to suppress warnings. I am looking for a way to "win" them. – IgorMenshikov Dec 07 '19 at 04:39
  • Main function result always can be cast to T. If you pass T as int, it will return some int value. Problem is T can be class (string or other class) or struct (int, decimal, Enum), so null logic is tricky here. – IgorMenshikov Dec 07 '19 at 04:43
  • 2
    This kinda defeats the purpose of having a strongly typed language... – Zohar Peled Jan 06 '20 at 05:01
  • Frankly, I don't understand what you're asking for here. The warning is completely legitimate. The way to "fix" it is to not write code that could potentially cast away a nullable type. There are lots of ways you could write the code differently, such that the warning would not occur, but none of them would do literally what you seem to want to do, so it's not clear any of those ways would qualify as an answer to _this_ question. – Peter Duniho Apr 10 '20 at 23:53

1 Answers1

-2

To make the compiler not worry about the null reference, just make sure that the object you want to cast is not null.

    [return: MaybeNull]
    public static T ToType<T>(object? value)
    {
        var res = ToType(typeof(T), value) ?? new object();
        return res is T generic ? generic : default;
    }

IMHO this way to handle types smells. What do you want to achieve with ToType? Maybe you can get something cleaner starting from that.

Alvin Sartor
  • 2,249
  • 4
  • 20
  • 36
  • OP said that the function can accept value types as well, so the constraints and `new()` are probably not appropriate. Your approach would likely be better served using `default(T)`, though I am still unsure if it is viable solution to OP's problem even with that. – ForeverZer0 Jan 05 '20 at 22:04
  • Thanks @ForeverZer0, even though the constraint `new()` does not preclude using value types, `default` is probably better and allow to remove the constraint. I'll update my answer. I also think that this might not be the solution. I feel that this might "win" the compiler warnings but is certainly not making the code cleaner. – Alvin Sartor Jan 05 '20 at 22:13
  • I'm getting downvotes but no one says why :p. Don't misunderstand me, I also don't like this implementation/way to handle the problem, but this is what solves @IgorMenshikov problem. – Alvin Sartor Jan 06 '20 at 22:18
  • 1
    I agree with Alwin. This solution can win a compiler warning but does not make the code cleaner. C# on github has issues about the same problem. Looks like current version of C# does not allow to do that clean. But technically this solution works (my tests were passed). Only one note: it could be reasonable to use a static object instead of creating a new one each time. This function can be called MANY times with "null" result and GC maybe unhappy. – IgorMenshikov Jan 10 '20 at 12:24
  • Well thought about the static object @IgorMenshikov. I don't feel that the problem is C# though. I feel that the language got to a point in which it allows to do a lot of things, but the user must be wise enough to chose the best path. – Alvin Sartor Jan 10 '20 at 17:22