- "It feels like someone is going to write a blog post about this."
Today, we took a look at expanded using
aliases, and open questions in the area. The LDM is generally in favor of the topic, but there are a few questions
to resolve around specific areas of the proposal.
First, we looked at pointer types in using aliases. We've heard from function pointer users, since before the first preview was publicly released, that they
would love to be able to using
alias long function pointer types. This raises an interesting question: where are unsafety errors reported for such types?
We don't have a using unsafe
today, so would we want to introduce that? Or would we want to check at the use-site, and not give any warning or error in the
using
itself? We enumerated a few options:
- Don't allow pointer types in
using
aliases, even with #4284 implemented. - Allow pointer types in
using
aliases, but introduceusing unsafe
and require it be present. - Always allow pointer types in
using
aliases, and check for unsafety at the use site.
An initial read was nearly unanimously in favor of 3, but further discussion revealed key concern: An unused using
alias might never be checked for pointer
types, even if the project doesn't have unsafe
turned on. This felt dangerous and likely to become an odd C# quirk that we would end up regretting. There
was also some preference that we ensure that any pointer type syntactic usage is explicitly tied to unsafe
in some fashion. We also think that using unsafe
will actually be easier to implement, as it will avoid some circularity issues that we'd otherwise need to be concerned about.
Given these concerns, we are planning to go with option 2, and potentially relax during preview or in a future version of C# based on user feedback.
Option 2, potentially relaxing in the future based on user feedback.
Next, we turned our attention to reference type nullability in aliases. Nested nullability is already allowed: using MyList = List<string?>;
, for example.
However, should we allow using NullableString = string?;
? There are some good reasons not to:
- Complicates implementation and conceptual load by forcing us to guard against
?
on nullable aliases. - Usage in pattern matching is broken. These aliases couldn't be used directly, and
{ }
patterns would need to fall to the underlying type.- This might further change in
#nullable disable
d contexts.
- This might further change in
- Display in quick info might change with nullable flow states: when an expression has been analyzed to be not null, it could require falling back to the
non-aliased underlying type, which we think is unexpected behavior. This behavior would also vary between
#nullable
contexts.
Top-level nullability cannot be specified in using
aliases.
Today, using NullableInt = Nullable<System.Int32>;
is legal. However, given our previous decision, do we want to also forbid using NullableInt = int?;
,
and require users to continue using Nullable<T>
for such locations? After some discussion, we think this is different than the previous point: string?
and
string
are the same runtime type, while int
and int?
are actually different runtime types; there is no difference in behavior around #nullable
contexts like there is for reference types.
Allowed.