Replies: 22 comments
-
Is there a general proposal for this? That is, any operation that takes a If I supply a non-nullable object as a nullable parameter, it works just fine, but when I supply a generic of a nullable as a generic of a non-nullable, it gives me a warning. It isn't null forgiveness that I need, but the opposite--non-null forgiveness, which I thought should be implicit and not really a conscious thing that we would have to do. |
Beta Was this translation helpful? Give feedback.
-
@szalapski I don't think that's true, for the same reason that any operation that takes a Let's say something expects a var list = new List<string>();
DoSomething(list); // This should, and does, cause a warning; you can't pass `List<string>` as `List<string?>`
Console.WriteLine(list[0].Length); // Or this happens
void DoSomething(List<string?> list) => list.Add(null); |
Beta Was this translation helpful? Give feedback.
-
You are right. Thinking it through, I intuitively expected that the |
Beta Was this translation helpful? Give feedback.
-
You use the nullability warning suppression operator, which is postfix DoSomething(list!); It's called the https://docs.microsoft.com/en-us/dotnet/csharp/language-reference/operators/null-forgiving operator, but I'm calling it the null-blindness operator and hoping it catches on. :D |
Beta Was this translation helpful? Give feedback.
-
It isn't null forgiveness that I need, but the opposite--non-null forgiveness, which I thought should be implicit and not really a conscious thing that we would have to do. |
Beta Was this translation helpful? Give feedback.
-
Nevertheless, the operator is a nullability warning suppression operator and is the way intended for you to suppress this particular nullability warning. |
Beta Was this translation helpful? Give feedback.
-
The nullability improvements working group discussed this issue on 24th October. Here are the notes: https://github.com/dotnet/csharplang/blob/main/meetings/working-groups/nullability-improvements/NI-2022-10-24.md. |
Beta Was this translation helpful? Give feedback.
-
Would that be limited to nullability only? There's a discussion on that as a general type inference feature: #92 which is what Java does already. |
Beta Was this translation helpful? Give feedback.
-
But why limit it to only nullability covariance? Making |
Beta Was this translation helpful? Give feedback.
-
That's very interesting. Apologies that I missed these comments when they were originally made. I'll try and take a look at this discussion when I can. |
Beta Was this translation helpful? Give feedback.
-
I think the reason is we feel better about breaking the rules if the feature is limited to just nullability. The result field in a Task is mutable, so on the "language-theoretical" level it's not safe to make it covariant. There might be some kind of guardrail you can insert which makes it "likely enough" that the requirements around safe covariant conversions won't be violated, but it's not clear. |
Beta Was this translation helpful? Give feedback.
-
It's probably too late now, but what are the downsides of creating and using something like I think option 1 is best. Yes, it introduces a certain amount of work, but I think it brings enough benefits to justify it. Option 0 has a smell to it - now the compiler has to remember a list of types, meh - and option 2 doesn't really work for |
Beta Was this translation helpful? Give feedback.
-
The working group notes talk about the idea of |
Beta Was this translation helpful? Give feedback.
-
I can't see how the immutable collections could use variance. They are not purely covariant. For example: https://learn.microsoft.com/en-us/dotnet/api/system.collections.immutable.immutablelist-1.add?view=net-7.0#system-collections-immutable-immutablelist-1-add(-0) An ImmutableList of strings is not one of objects. You would not be able to add an object to the actual instance, despite the type implying it was possible. |
Beta Was this translation helpful? Give feedback.
-
I'm proposing that |
Beta Was this translation helpful? Give feedback.
-
Interesting concept :-). I could envision something like that being possible. |
Beta Was this translation helpful? Give feedback.
-
In addition to what @sab39 wrote. other types don't have such a limitation, for example, |
Beta Was this translation helpful? Give feedback.
-
This sounds like something interesting, but it seems to touch on full covariance on types, rather than nullable covariance which is purely compiler-sugar but currently a friction point. One solution for the issue about nullability and Concretely, like the OP says, this produces an warning: public Task<string?> GetAsync() => Task.FromResult(""); But an attribute could be placed on public static Task<T> FromResult<[NullableCovariant] T>(T value); The effect here would be that at callsites of this method, if the inferred type argument is a (non-nullable) reference type and the output is target typed to the nullable version of the type argument, the compiler is allowed to lift the inferred type argument to the nullable version. |
Beta Was this translation helpful? Give feedback.
-
I'd rather have the attribute on the type parameter of using System.Threading.Tasks;
static class C {
static void M(out Task<string?> task) {
N(out task);
}
static void N(out Task<string> task) {
task = Task.FromResult("");
}
} even though I suppose it's quite easy to suppress warnings by adding |
Beta Was this translation helpful? Give feedback.
-
Yeah, I was thinking about as a separate and longer term idea. Should I start a discussion to propose it as such? |
Beta Was this translation helpful? Give feedback.
-
Come to think of it, the Task<object> FooAsync()
{
return Task.FromResult(""); // currently this is an error, but it would be helpful if it worked
}
Task<objecct> BarAsync()
{
return Task.FromResult(0); // to make this work, it would be outside of the scope of regular covariance,
// but would be cool nonetheless
// if we go with the "target-typing" approach, and not the covariance approach, this should work fine
} |
Beta Was this translation helpful? Give feedback.
-
Anything new here? Got my self in this situation, not only with Have a method and cant make an overload for this because string is a reference type and those types are identical: My hacky workaround would be something like
This should really be fixed because it affects all generic types and their usage as parameters..... //EDIT: To clarify more: I dont want those two overloads, but right now i cant express to the compiler, that i want a function that takes //EDIT2: //EDIT3: //EDIT4: |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Task<T>
nullability covarianceChampion issue: #8997
Summary
Task<T>
nullability covariance (LDM tentatively approved, needs design proposal for task-like types)It should be possible to return a
Task<string!>
for aTask<string?>
.Motivation
See some examples of this problem: dotnet/roslyn#40759, dotnet/roslyn#40757
Unresolved questions
Design meetings
Split issue from #3868
https://github.com/dotnet/csharplang/blob/main/meetings/2022/LDM-2022-09-28.md#nullability-improvements
https://github.com/dotnet/csharplang/blob/main/meetings/2024/LDM-2024-09-06.md#taskt-nullability-covariance
Beta Was this translation helpful? Give feedback.
All reactions