allowNullable?
#129
Replies: 3 comments
|
The short version is: it looks like a deliberate overload-resolution hack.
The important part is that nullable reference annotations such as: Tversus: T?are primarily compile-time nullability information. They do not give you two distinct CLR reference types that can simply be used to define otherwise identical overloads. So if the library wants both a nullable-aware and a non-nullable form of something conceptually like: SubscribeSafe(
IObservable<T> source,
Action<T> onNext,
Action<Exception> onError)and: SubscribeSafe(
IObservable<T?> source,
Action<T> onNext,
Action<Exception> onError)it needs some other difference in the actual parameter list. That seems to be what this is doing: params bool[] allowNullableBecause it is a source.SubscribeSafe(onNext, onError);but at the metadata/signature level the method now has an additional parameter, so the two overloads can coexist. The name: is therefore a bit misleading. It is not really an "allow nullable" switch that the implementation reads. It is more like: The other part of the mechanism is: [OverloadResolutionPriority(1)]which tells newer C# compilers to prefer this overload over otherwise competing overloads when resolving the call. So I believe the intent is roughly:
That is also why the documentation says:
rather than describing what values should be passed to it. I agree that it is a pretty unusual pattern. I would probably have called the parameter something like So unless there is some other use of the array elsewhere in the implementation, I would read it purely as an overload-resolution/signature marker rather than an application-level parameter. |
|
Alright, that make sense. I think it definitely needs that extra documentation clarity. However, now I'm left asking..... why? What is the significance of having this operator know whether Am I to assume that this operator null-checks those values, and DOESN'T pass them to Why yes, that is in fact EXACTLY what this operator is doing. So, any consumer of this library that happens to make a nullability mistake when using this operator will just get to find out about it in production, instead of having the compiler do what it's supposed to and tell them at design time. Is this some kind of obscure CLS or COM compatibility requirement? |
|
Thanks for digging into the implementation — I think your reading of it is correct. I went back and checked both the code and the C# nullability rules, and I don't see any runtime null check in this overload. The key line is: return SubscribeSafeCore(
source,
Witness.Create<T?>(value => onNext(value!), onError));The So if onNext(value!)still passes That means the concern you raised about the signature seems valid. The source is: IObservable<T?>while the callback is: Action<T>For nullable reference types, For example: IObservable<string?> source = ...;
source.SubscribeSafe(
value => Console.WriteLine(value.Length),
ex => Console.WriteLine(ex));The consumer gets no nullable warning for I also checked whether So my current reading is:
What I can't determine from the implementation alone is why this overload intentionally uses There may be some historical API compatibility or parity reason, but I wouldn't want to guess without a design note or maintainer comment confirming it. So I think your concern is reasonable: if forwarding I may be missing some historical constraint here, so I'd be interested to hear if a maintainer can shed some light on the original intent. |
Uh oh!
There was an error while loading. Please reload this page.
What on earth is the purpose of a throwaway
paramsargument here?"Reserved for nullable overload resolution" doesn't really explain anything. This is not a pattern I've ever seen before.
All reactions