Git Product home page Git Product logo

Comments (100)

Thaina avatar Thaina commented on July 17, 2024 64

Should we also support &&= and ||= operators?

Yes please

from csharplang.

yaakov-h avatar yaakov-h commented on July 17, 2024 38

@CyrusNajmabadi Wouldn't that still unconditionally evaluate the right-hand side? I'd expect in a situation such as:

var val = true;
val &&= BigExpensiveOperationReturningBool();

that BigExpensiveOperationReturningBool is not executed.

from csharplang.

Thaina avatar Thaina commented on July 17, 2024 25

@paulomorgado

var mustAllTrue = Condition0;
mustAllTrue &&= Condition1;
mustAllTrue &&= Condition2;

from csharplang.

MgSam avatar MgSam commented on July 17, 2024 24

Glad to see this feature graduated from the "we will never do this!" bucket. :)

from csharplang.

CyrusNajmabadi avatar CyrusNajmabadi commented on July 17, 2024 20

@Thaina You can already do that today with:

var mustAllTrue = Condition0;
mustAllTrue &= Condition1;
mustAllTrue &= Condition2;

from csharplang.

alrz avatar alrz commented on July 17, 2024 20

This proposal would allow to null check an expression without assigning it (if permitted),

arg ??= throw new ArgumentNullException(nameof(arg));
// instead of
_ = arg ?? throw new ArgumentNullException(nameof(arg));

It could also be used with return, continue and break expressions.

from csharplang.

CyrusNajmabadi avatar CyrusNajmabadi commented on July 17, 2024 13

@CyrusNajmabadi Wouldn't that still unconditionally evaluate the right-hand side?

Ah, point taken.

from csharplang.

paulomorgado avatar paulomorgado commented on July 17, 2024 10

if val is true, that means that it will end up with whatever BigExpensiveOperationReturningBool() returns, right?

Short circuiting would only happen for:

var v1 = false;
v1 &&= BigExpensiveOperationReturningBool();

var v2 = true;
v1 ||= BigExpensiveOperationReturningBool();

I'll agree that move statements to expressions can be more expressive.

from csharplang.

alrz avatar alrz commented on July 17, 2024 9

dotnet/roslyn#13951 and dotnet/roslyn#1276 are also related here.

obj?.Property = value;
obj?.Event += handler;

from csharplang.

devinvisible avatar devinvisible commented on July 17, 2024 6

Very excited for this! Nice syntactic sugar similar to Ruby's ||=

from csharplang.

HaloFour avatar HaloFour commented on July 17, 2024 6

@arekbal

I believe the final goal is to have null eradicated

That is not a goal of the C# language.

from csharplang.

HaloFour avatar HaloFour commented on July 17, 2024 6

@rjgotten

a ??= b ?? a;

😁

from csharplang.

SetTrend avatar SetTrend commented on July 17, 2024 5

Allow Null-conditional operators to be lvalues: dotnet/roslyn#13951

from csharplang.

GeirGrusom avatar GeirGrusom commented on July 17, 2024 5

Pushing for more support of null handling is counter productive as it makes it even harder for the future of C# to eradicate null construct from the 'safe' language.

C# will always have null. The only way forward is to properly deal with it.

from csharplang.

yaakov-h avatar yaakov-h commented on July 17, 2024 5

The more I think about it, the more I tend to agree and think that a ??= b should assign b to a (if null), preserve the type of a, but the expression itself should have the nullability of b, i.e.:

string? a = null;
a ??= "hey";
// a is still string?.

int? b = null;
var c = b ??= 5;
// b is int?.
// c is int.

int? d = 5;
var e = d ??= null;
// d is int?
// e is int?

from csharplang.

CyrusNajmabadi avatar CyrusNajmabadi commented on July 17, 2024 3

@TonyValenti |= and &= already exist and can be used today :) They already have the semantics you'd want here for booleans.

from csharplang.

GeirGrusom avatar GeirGrusom commented on July 17, 2024 3

In many ways these concepts simplify code otherwise very verbose (such as separate properties HasError and then Error)

This is union types, not option types?

C# and the CLR runtime both have an option type built into the language, and unfortunately it's all reference types. We need to deal with that, not add yet another option type into the runtime.

The mistake wasn't null, it was not making the compiler emit information about null and not forcing the programmer to deal with it. This doesn't have to be a runtime type, and both Kotlin and TypeScript has clearly shown this. What C# is missing isn't an option type because it already has one. What C# needs is a non-nullable type, and the plan here is to promote normal reference types to be non-option types in C# and provide a new syntax for option types: T?. This is consistent with the language.

Functional programming languages has option types because they don't have the null concept so just shoehorning in an option type in C# is the wrong way to go.

from csharplang.

CyrusNajmabadi avatar CyrusNajmabadi commented on July 17, 2024 3

@333fred FWIW, i agree with @jnm2 here. I would put this in the category of a 'foolish consistency'. Basically, in a very real sense, it feels like the language throwing away information it knows for certain, making things work more poorly for the user. i.e. the language knows for certain that the value is non-null. But it forces the representation to be a nullable value.

This adds friction and pain for the case where the user wants the actual value. Whereas, the reverse is not true. i.e. you can pass a normal value to anyone who needs a nullable-value easily. But the opposite (which is what the lnaguage is doing here) isn't true.

--

I get the simplicity of not doing anything special here. But, i would also argue that that goes against the spirit and purpose of the ?/?? ops.

Thanks for your consideration :)

from csharplang.

rjgotten avatar rjgotten commented on July 17, 2024 3

What about the reverse of this operator? I.e. a conceptual a =?? b only assigning b to a when b is non-null. Could be very nice for object initializer syntax where null values are skipped over during assignment, retaining whatever value was set as the default value for a property in the class constructor.

from csharplang.

yaakov-h avatar yaakov-h commented on July 17, 2024 3

LDM Update: The result of the ??= expression will be the result of an implicit conversion from the RHS to the underlying type of the LHS, if one exists.

That means that #34 (comment) will happen (and hey, it looks like my exact example was used in the LDM 😄)

from csharplang.

333fred avatar 333fred commented on July 17, 2024 3

@jnm2 @yaakov-h dotnet/roslyn#36329 and #2591. We're hoping that this change will be in the final version of 16.2 or some preview before then.

from csharplang.

paulomorgado avatar paulomorgado commented on July 17, 2024 2

@Thaina, what are the use cases for &&= and ||=.

from csharplang.

yaakov-h avatar yaakov-h commented on July 17, 2024 2

@paulomorgado true. 😅

from csharplang.

ashmind avatar ashmind commented on July 17, 2024 2

Note that I did a prototype for this one a while ago, at ashmind/roslyn@cf5ee99.

It was available on TryRoslyn for a while, but fell too far behind main roslyn branch at the moment -- I'll see if I can merge with latest.

from csharplang.

TonyValenti avatar TonyValenti commented on July 17, 2024 2

Definitely a big fan of this one. Really hoping to see ??= ||= and &&= . I've found myself wanting all three of them!

from csharplang.

333fred avatar 333fred commented on July 17, 2024 2

@jnm2 @alrz ?. as an lvalue is not part of what I'm working on. I see the use case in the event that the operator is a ??=, or an event assignment (though this one is harder as an implementation detail), though I definitely cannot see it as part of a more general use case. I'll bring it up with LDM and see if there's any palate for it as part of the feature.

from csharplang.

333fred avatar 333fred commented on July 17, 2024 2

@ufcpp this cannot be int here. a ??= b is approximately equivalent to a ?? (a = b). The type of a = b is A, and the type of a ?? A is A, which must therefore be int?. This was a deliberate design decision on our part.

from csharplang.

333fred avatar 333fred commented on July 17, 2024 2

@jnm2 I'll see if LDM has the appetite to reconsider this, but again FWIW we did consider this and decided on the current representation.

from csharplang.

yaakov-h avatar yaakov-h commented on July 17, 2024 2

Yes.

from csharplang.

jnm2 avatar jnm2 commented on July 17, 2024 2

@yaakov-h at #34 (comment):

LDM Update: The result of the ??= expression will be the result of an implicit conversion from the RHS to the underlying type of the LHS, if one exists.

That means that #34 (comment) will happen (and hey, it looks like my exact example was used in the LDM 😄)

@333fred This change made a real difference to me today. Thanks again!

private bool? foo;

public bool Foo => foo ??= Properties.GetDataSourceRowByKeyValue(EditValue) is null;

from csharplang.

MgSam avatar MgSam commented on July 17, 2024 1

@Spongman To be fair, Mads said in that thread he thought ??= might be worthwhile, but ||= and &&= were probably not given the finite budget for features. I agree with him on that.

from csharplang.

hickford avatar hickford commented on July 17, 2024 1

https://github.com/dotnet/csharplang/blob/master/proposals/null-coalecing-assignment.md

There have been at least eight separate community requests for this feature.

It's hard to search the web for ??=. I came by https://stackoverflow.com/questions/655762/a-null-coalescing-assignment-operator

from csharplang.

yaakov-h avatar yaakov-h commented on July 17, 2024 1

In theory:

With Option, Option<T> suggests that there may or may not be a value available. T suggests that there is always a value available. This more clearly reflects the intent of the code.

With null, null can infect any (reference type) value. Every single T is T-or-null-maybe-who-knows.

#36 kinda of solves it, not really, but probably close enough for most practical uses.

from csharplang.

CyrusNajmabadi avatar CyrusNajmabadi commented on July 17, 2024 1

@arekbal You have the burden of proof backward. You stated:

I believe the final goal is to have null eradicated from the 'safe' language layer

If that is your belief, the onus is on you to provide evidence that that's the case. Note: i was an LDM member for 10+ years, and i can say that i don't recall that ever being stated as any sort of goal ('final' or otherwise) :)

If you think otherwise, please explain your position.

from csharplang.

CyrusNajmabadi avatar CyrusNajmabadi commented on July 17, 2024 1

you didn't address my point :) You made a claim, but that claim is not backed by any actual evidence. There is no goal (implied or otherwise) for C# or .net "to have null eradicated from the 'safe' language layer"

Eradicating nulls or letting them to be some sort of Nothing/None would be fine to me.

This is not going to happen. Nulls are not being eradicated. There are billions of lines of code out there that use null. That's going to still continue to be hte case. This feature is about ensuring that the usage of those nulls doesn't unexpected lead to null-ref exceptions at runtime.

Just, current state of affairs, where being on safe side means you have to ? every reference type member and check every such parameter is IMHO unacceptable.

You don't have to ? every reference type. You don't even have to use this feature. You can opt-into using thsi feature if you want, and you would then mark the code that can be null. The compiler will then assist you by telling you places you need to then be safe about code that might then cause dereferences of null values.

from csharplang.

CyrusNajmabadi avatar CyrusNajmabadi commented on July 17, 2024 1

What is the difference between what I wrote about "'safe' layer" and what you just described?

Well, for one thing, there is no part that involves "null eradication" :)

I didn't made a claim.
I believe the final goal is to have null eradicated

That is a claim. That's your claim about what the final goal is. I get that it's your belief. But all that has been pointed out is that your belief doesn't match reality. There's no need to take offense when that is pointed out :)

Which is I infer more or less about slowly eradicating nulls and replacing them with Nullable/NonNullableReferences so such annoying constructs as mentioned above wouldn't be necesarry.

You are incorrect. Both of these can (and will) still contain nulls. All that is happening is that the compiler will more aggressively warn you when it thinks there is a reasonably likelihood that what you're doing could blow up at runtime.

I hope that helps clear things up :)

from csharplang.

CyrusNajmabadi avatar CyrusNajmabadi commented on July 17, 2024 1

Another one slashing the same quote at same place...

Your full statement was:

I believe the final goal is to have null eradicated from the 'safe' language layer and having a replacement in a form of far more explicit Option/Maybe value.

This full claim is unsupported as well. This is not any sort of goal for C#. There is no goal to move it to a 'more explicit Option/Maybe value'. There is no goal to eradicate null from the 'safe' language layer.

The very explicit goal is: to allow users to provide information to the compiler about null and have the compiler then check if their code does something potentially unsafe with nulls. Neither eradication of nulls, nor explicit Options/Maybe are the goals now or for the future.

from csharplang.

CyrusNajmabadi avatar CyrusNajmabadi commented on July 17, 2024 1

Assuming I have it enabled in my project... would I be able to safely (as in statically provable by compiler it is fine) omit ? and ?? from company?.Person?.Name ?? ""

No. You would not be able to safely do that. None of this stuff is provable. And it will be possible to violate that.

That said, by and large this should not really happen. But it's not statically provable. And making the compiler so restrictive that it could proven would actually feel too onerous to be palatable for user.

even though they align with what is going on

They don't align. That was my point :)

from csharplang.

jnm2 avatar jnm2 commented on July 17, 2024 1

In my personal experience, null in itself isn't the issue.

This is exactly right. null itself doesn't cause grief. The issue is null-blind type systems which conflate reference-typed contracts with null, a thing which no more fulfills the contract than some other random reference type.

from csharplang.

HaloFour avatar HaloFour commented on July 17, 2024 1

@arekbal

The use if the ?. operator will result in a nullable value. It doesn't change the semantics of the code.

But if GetClassInstance() and the Company property both return non-nullable references then you, as a developer, can have some confidence that you shouldn't have to use ?. in the first place.

from csharplang.

ufcpp avatar ufcpp commented on July 17, 2024 1
#nullable enable

// for reference types
static void M(string? x)
{
    var y = x ??= "";

    // equivalent to:
            
    string y = x ?? (x = "");
            
    // inferred type of y is string (non-nullable).
}

// for nullable value types
static void M(int? x)
{
    var y = x ??= 0;

    // equivalent to:

    int? y;
    if (!x.HasValue)
    {
        x = 0;
        y = x;
    }
    else
    {
        y = x;
    }

    // inferred type of y is int? (nullable).
    // I want this changed to:

    if (!x.HasValue) x = 0;
    int y = x.GetValueOrDefault();

    // so that y is inferred as int (non-nullable).
}

from csharplang.

ufcpp avatar ufcpp commented on July 17, 2024 1

@YairHalberstadt
I want it to be int.

from csharplang.

jnm2 avatar jnm2 commented on July 17, 2024 1

The thing that bothers me is that I should be able to do this, probably 80% of the time I'd be using ??= that I've noticed in the past few years:

private int? foo;

private int GetFoo()
{
    return foo ??= Expensive();
}

Why is an abstract consistency important enough to force me to do return (foo ??= Expensive()).Value;?
(Or .GetValueOrDefault() if I don't want a perf penalty?)

Also imagine passing the result of the ??= operator to other int targets, such as method parameters or properties or existing int variables.

from csharplang.

Shawn-Twinmaple avatar Shawn-Twinmaple commented on July 17, 2024 1

I would like to have the inverse as well
?!=
i.e. not assigning the value if the right hand side is a null:

I think this would work well in combination with the existing null-conditional operator and nullable reference types:

#nullable enable
byte[]? Data = { 1, 2, 3 };

void DoStuff() => this.Data ?!= this.device?.ReadDataFromStream();

instead of having to do all this:
void DoStuff()
{
var temp = this.device?.ReadDataFromStream();
if (temp != null)
this.Data = temp;
}

i.e. if this.device is a null Nullable or .ReadDataFromStream() returns null, then .Data isn't set to null.

from csharplang.

PathogenDavid avatar PathogenDavid commented on July 17, 2024 1

@gafter I think you hit the close+comment button by mistake.

from csharplang.

333fred avatar 333fred commented on July 17, 2024 1

@ufcpp no compound assignment works that way, and it would conflict with the nullable-value-type change that was just implemented.

from csharplang.

Spongman avatar Spongman commented on July 17, 2024

@MadsTorgersen very glad to see you finally changed your mind on this "contrived" scenario ;)

https://connect.microsoft.com/VisualStudio/Feedback/Details/585580

from csharplang.

 avatar commented on July 17, 2024

@Thaina

Yes please

It is not an opinion... just text...

Yes it should be implemented but guys please consider real discussion provided here: #397

from csharplang.

svick avatar svick commented on July 17, 2024

@CyrusNajmabadi

They already have the semantics you'd want here for booleans.

They do not: #34 (comment).

from csharplang.

CyrusNajmabadi avatar CyrusNajmabadi commented on July 17, 2024

Lol. in the same thread no less. I really need to internalize this.

from csharplang.

jnm2 avatar jnm2 commented on July 17, 2024

dotnet/roslyn#13951 and dotnet/roslyn#1276 are also related here.

obj?.Property = value;
obj?.Event += handler;

@333fred Have you enabled this syntax for C# 8.0, or would you consider it?

from csharplang.

alrz avatar alrz commented on July 17, 2024

even if that doesn't work, I'd expect obj?.Property ??= value to work. so now it seems like a "missing" feature: you have the compound assignment but not the simple assignment.

from csharplang.

AustinBryan avatar AustinBryan commented on July 17, 2024

Can't wait for this. It's such a common thing to run into

from csharplang.

UpperAvenue avatar UpperAvenue commented on July 17, 2024

@333fred has there been any movement on this?

from csharplang.

arekbal avatar arekbal commented on July 17, 2024

Pushing null helpers everywhere is IMHO "plain" insane.

Why there is no push for optimized Option<>, Result<>, DiscriminatedUnions instead?

from csharplang.

HaloFour avatar HaloFour commented on July 17, 2024

@arekbal

Discriminated unions are championed. They'll likely get more attention after recursive pattern matching ships.

#113

As for "optimized" Option<> or Result<> types, what specifically are you proposing from the language to support these? You're free to define such types now, and if you want reference implementations in .NET you could request that through the CoreFX repository.

And even if such types were added they would not replace all of the existing APIs that depend on normal reference types.

from csharplang.

Thaina avatar Thaina commented on July 17, 2024

@arekbal What would be any difference between Option and null ?

from csharplang.

arekbal avatar arekbal commented on July 17, 2024

@Thaina
in case of Nullable<> there is a little of significant difference. It makes a lot of difference for fields, properties, parameters etc. of reference types.
@HaloFour
I believe the final goal is to have null eradicated from the 'safe' language layer and having a replacement in a form of far more explicit Option/Maybe value.
That, of course involves multiple parts such as marshalling to be improved/changed for cases involving null pointers, not-assigned fields, properties, some special compiler treatment of such Option/Maybe type and so on.
I am aware and quite glad of ideas that are being introduced and what is in the works but...

Pushing for more support of null handling is counter productive as it makes it even harder for the future of C# to eradicate null construct from the 'safe' language.

from csharplang.

arekbal avatar arekbal commented on July 17, 2024

@GeirGrusom

C# will always have null.

Quite a strong statement. Could you back that up with anything meaningful?

@HaloFour
If you quote me, please do that properly. That is the full quote:

the final goal is to have null eradicated from the 'safe' language layer

You did this on purpose... I see no point in restating what I meant.

That is not a goal of the C# language.

Where did I stated that is the goal for the whole C# language? We are talking in context of null handling. Intentional... again.

Please tell me then, what the goal of C# language is. That is a new one...

from csharplang.

HaloFour avatar HaloFour commented on July 17, 2024

@arekbal

The remainder of that quote is meaningless. There are no championed proposals to take the handling of null further than this one and there is no "final goal" to migrate from the use of nullable references to Option/Maybe. C# not only will continue to have null but it's use will still be considered idiomatic.

from csharplang.

arekbal avatar arekbal commented on July 17, 2024

@HaloFour

The remainder of that quote is meaningless.

It is not 'meaningless' as I do understand that in language of such history, disabling nulls would mean some special switches, flags, or modes. I also think null pointers are just part of pointer arithmetics which is very useful at some 'unsafe' level. Rust tries to do this well enough IMO. std is full of unsafe { } but at the higher layers sane people hide pointers. Wow... C# has just unsafe keyword just to hide pointers behind this kind of layer.

@HaloFour
I stated 'I believe', you stated you know what longterm C# language design goals aren't. It is difference.

@CyrusNajmabadi
^^^
Null safety at some level of language, by convention or enabled by some switch, is as common as sand in the desert among Modern Languages. Here is a safe short list (Rust, TypeScript, Swift, Haskell, Kotlin, C#).
Latest additions to C# such as string? are null safety improvements. That exact feature - to fully work as intended - would require some sort of flag to reverse the default behavior. The very same thing I am advocating for, in the future so the constructs like company?.person?.name wouldn't be necesarry (unless all of them got explicitly declared options/nullables/maybes/string?/whatever-you-wanna-call-it).
I don't know, you guys, or me are

'plain' insane

if you suggest some of current changes aren't going null-safety direction. Even that 'Champion' is about dealing with nulls.

Eradicating nulls or letting them to be some sort of Nothing/None would be fine to me.
Just, current state of affairs, where being on safe side means you have to ? every reference type member and check every such parameter is IMHO unacceptable. Especially, when improvements in performance seem to became another lmportant long-term goal.

from csharplang.

arekbal avatar arekbal commented on July 17, 2024

That is just offensive.
I didn't made a claim. I said 'I believe' as in made an educated guess such as opened the first page of issues and spotted this:
https://github.com/dotnet/roslyn/issues?q=is%3Aissue+is%3Aopen+label%3A%22New+Language+Feature+-+Nullable+Reference+Types%22
Which is I infer more or less about slowly eradicating nulls and replacing them with Nullable/NonNullableReferences so such annoying constructs as mentioned above wouldn't be necesarry.

There are billions of lines of code out there that use null. That's going to still continue to be hte case.

Which is exactly what I stated before. And yet that is exactly what seems devs are doing and trying to handle in their capacity. They seem to start marking code that could(or not) return null (as to mark it, as effectively nullable or not(read: an option type)) with proper attributes.

You don't have to ? every reference type. You don't even have to use this feature...

Same about this new 'nullable' compiler flag...
What is the difference between what I wrote about "'safe' layer" and what you just described?

from csharplang.

arekbal avatar arekbal commented on July 17, 2024

Another one slashing the same quote at same place...
That is a claim:

That is not a goal of the C# language.

as opposed to what I wrote. Easily comparable.
It seems we differ in size of glasses. Let's just agree to disagree. 👍

Both of these can (and will) still contain nulls

So, if you feel educated enough about the general direction these changes are going... you might kindly answer the upcoming question.
Would I, at some point in time in the future, ever, be able to 'ask' compiler to verify that my application is not assigning null or forgetting to assign something, or I am assigning something in wrong order, or I am just passing null to function...? Of course, external inputs and 'unverified' code would have to be checked inside my application...
Then... whata about this: dotnet/roslyn#22152
[NonNullTypes] and so on...
Where would that be injected if not on code that got verified to not itself generate nulls? Please explain.

Thank you for the discussion and very much in advance.

from csharplang.

HaloFour avatar HaloFour commented on July 17, 2024

@arekbal

That attribute exists to inform the compiler to apply nullability tracking analysis to either your assembly or for referenced assemblies. The compiler doesn't add it when it determines that null dereferencing can't happen. The developer has to add it.

What that feature does is emit warnings on potential null dereferencing, based on the nullability of the reference specified by the ? suffix on the type. Flow analysis tracks the nullability of that reference through a method to determine the potential nullability. Unless you tell the compiler to treat those warnings as errors a potential dereference will not break the build. You'll still end up with an assembly that contains a potential null dereference. Also, the language will include a ! postfix operator which will suppress those warnings, allowing the developer to override the compiler.

This feature isn't intended to remove nulls, it's intended to allow the developer to declare where they might expect nulls so that other developers can act accordingly.

from csharplang.

CyrusNajmabadi avatar CyrusNajmabadi commented on July 17, 2024

Where would that be injected if not on code that got verified to not itself generate nulls? Please explain.

I think you have this somewhat backward. Like with normal Types, the idea here is that the developer informs the compiler about hteir intent, and the compiler validates the code doesn't violate that intent.

from csharplang.

arekbal avatar arekbal commented on July 17, 2024

@HaloFour
So, it is like green tomatoes now. Neat. 👍

@CyrusNajmabadi
Isn't string? and the sorts a Option/Maybe/Nullable family? It's a type that you have("if you enable the feature with attribute lol") to explicitly check for not being the null/Nothing/None value otherwise code wouldn't compile. In couple of languages on Wikipedia nulls are classified as Option types "no value". That ? operator seems to quack, but whatever.

Introduction of this extra attribute is an introduction of another, higher safer layer.
Sorry again, for not seeing my mistake then.

@CyrusNajmabadi @HaloFour
I am asking, to gain the understanding and it seems straight, how I would imagine in to work in short term future.

Back to the [NonNullTypes]...
Assuming I have it enabled in my project... would I be able to safely (as in statically provable by compiler it is fine) omit ? and ?? from company?.Person?.Name ?? ""

From my POV you guys just got offended by anon, with his opinions, beliefs and so called claims about the way to move forward, even though they align with what is going on, just because he is anon(just having a look around) and not contractual part of the team. IMO that is just weak. 🐰

from csharplang.

GeirGrusom avatar GeirGrusom commented on July 17, 2024

Pushing for more support of null handling is counter productive

@arekbal that's a strong statement. Can you back it with anything meaningful?

In my personal experience, null in itself isn't the issue. Null is well handled in Kotlin without Maybe and Optional wrappers, which in my experience will make the issue a lot worse because of how extremely verbose this concepts end up. Java's Optional<T> being a very good example.

Kotlin however takes the route that for the most you don't have to deal with null and when you do the language will explicitly forbid you from not checking for it without any type wrappers.

What you need is a feature where the language forces you to handle it with ?. or ?? or a value check.

from csharplang.

arekbal avatar arekbal commented on July 17, 2024

@GeirGrusom

because of how extremely verbose this concepts end up

That is not true.
In many ways these concepts simplify code otherwise very verbose (such as separate properties HasError and then Error). Result helps with Error Code 'driven' control flows instead of very verbose and just slower try catch blocks.
Here are some C# examples.

There is also this.
Which have a lot of helpers that might feel overwhelming, but they are just that, helpers...

What you need is a feature where the language forces you to handle it with ?. or ?? or a value check.

That is an exemplary unreasonable statement IMO. Just because Java(Kotlin included) and C# let nulls in, now it might be fine to pollute code with ifs at every dereference and then hope for the compilers to remove it, wherever it can, which is highly unlikely?!?

What you need is a goodwill assumption that all reference types are non-null, unless explicitly nullable(thats what we were doing for decades). It is stupid otherwise. And I am advocating against it.

But again, nulls, let that be. Make Nullable<T> handle reference types, let us limit the amount of checks on parameters, members to bare minimum(such as program inputs, native code), ignore reflection and the gang aaaand done... null safe code could be proved at some level of assumptions.

from csharplang.

yaakov-h avatar yaakov-h commented on July 17, 2024

That sounds strikingly similar to what #36 is working towards...

from csharplang.

GeirGrusom avatar GeirGrusom commented on July 17, 2024

Yes, exactly. I'm opposed to adding more option types in the runtime if the compiler can handle it without it. Fixing the null handling is not a binary breaking change like adding a runtime option type is.

from csharplang.

arekbal avatar arekbal commented on July 17, 2024

The mistake wasn't null, it was not making the compiler emit information about null and not forcing the programmer to deal with it.

Again... that is unreasonable... you want to unnecessarrily pollute the code with checks... not even contracts... just a runtime check for nulls everywhere nullable type is used. That is nonsense. There is a lot of places... for instance factory methods (lol) where we can be sure, constructed/returned type is not null.
I hope we are misunderstanding each other and we are in the end want the same by through different means... but from what you wrote it seems not.
Union types... just for practicality, languages have them both, sometime Option is not integrated much, but just implemented as Union, Deeper integration allows for some optimizations... such as using that null ptr for None value with nullable types, or using non defined value for Enums, or NaN for floating points. Rust goes so far as to employing NonZeroInts and so on, just so Option of such type would align well. It is some sort of partial specialization which is hard to do in C# directly (currently) without obvious hacks but at compiler level, pretty much possible.
So again, that could be even implemented over improved Nullable...

from csharplang.

333fred avatar 333fred commented on July 17, 2024

@UpperAvenue avenue, to answer your question: this has been implemented and merged, and will be in the first previews of the next version of VS.

from csharplang.

GeirGrusom avatar GeirGrusom commented on July 17, 2024

Again... that is unreasonable... you want to unnecessarrily pollute the code with checks... not even contracts... just a runtime check for nulls everywhere nullable type is used.

No? That's the exact opposite of what I want.

What I want is for the compiler to keep track of that contract. You don't have to null check non-null types, and doing a null check on a nullable type will cause the compiler to consider that the type for that variable changed even if it didn't actually change to the runtime. The compilers type system is different

string? s = GetNullable();

if(s is null)
{
  // type of s in this block will be string? (i.e. nullable)
}
else
{
  // type of s in this block will be string (i.e. non-nullable)
}

This is how it works in Kotlin. Type checking a variable will effectively change the type of that variable in that block.

from csharplang.

arekbal avatar arekbal commented on July 17, 2024
Person p = GetClassInstance();
if(p?.Company?.Name is null)
{
}

or

Person? p = GetClassInstance();

That is the problem. is Person? a Nullable<Person>? How about it's properties... are they all explictly Nullable?

from csharplang.

YairHalberstadt avatar YairHalberstadt commented on July 17, 2024

@ufcpp
What if you wrote var y = x ??= null;

from csharplang.

YairHalberstadt avatar YairHalberstadt commented on July 17, 2024

@ufcpp
As far as I can make out from the spec, what you're describing sounds like a bug anyway

from csharplang.

jnm2 avatar jnm2 commented on July 17, 2024

I wish an exception could be made, making this more first-class instead of thinking of it as merely a ?? (a = b). It would make the type system feel smarter.

from csharplang.

333fred avatar 333fred commented on July 17, 2024

@jnm2 we did consider it, but we didn't want to make ?? = inconsistent with all other assignments where its type could be different from the lhs.

from csharplang.

jnm2 avatar jnm2 commented on July 17, 2024

If it was inconsistent with all other assignments this way, what would the difficulty be?

from csharplang.

333fred avatar 333fred commented on July 17, 2024

That is the difficulty in and of itself. We did not want to make an assignment that differs in this way. https://github.com/dotnet/csharplang/blob/c81b99f4c965dbb6e9819a10a2e010db4c859f6f/meetings/2018/LDM-2018-07-16.md#result-type-of-the-expression

from csharplang.

Suchiman avatar Suchiman commented on July 17, 2024

It would be inconsistent with assignments but consistent with how ?? works and how nullable reference types determines nullness based on flow analysis. But then there would be also no way to opt-out if you might want to assign null again later on 😕 and the workaround of var z = x ?? y seems fair enough.

from csharplang.

yaakov-h avatar yaakov-h commented on July 17, 2024

Could that case be solved by flow analysis in #1865?

from csharplang.

jnm2 avatar jnm2 commented on July 17, 2024

I thought of that, but it seems less clean. It would mess with inference; foo.Select(x => x.Bar ??= CalcBar(x)) would return a sequence of nullables. Also, I have structs with a Value property. You'd have to do .Value.Value instead of .Value. It doesn't make sense to even be able to access the members of Nullable<>.

from csharplang.

orthoxerox avatar orthoxerox commented on July 17, 2024

@HaloFour this looks like one of those terrible and useless interview questions. 😁

from csharplang.

jnm2 avatar jnm2 commented on July 17, 2024

@333fred Earlier in the thread, a few of us expressed that strict consistency brings papercuts more than it brings value. Since this is the kind of thing that can't be fixed once it ships, would you be kind enough to consider speccing it so that var foo = _foo ??= fallback; results in foo not being Nullable<> unless fallback is Nullable<>?

from csharplang.

jnm2 avatar jnm2 commented on July 17, 2024

@333fred I really appreciate it!

from csharplang.

gafter avatar gafter commented on July 17, 2024

@Shawn-Twinmaple This feature is (likely to be) going into C# 8. If you have a different language feature that you'd like to propose, please open a new issue for that.

from csharplang.

Thaina avatar Thaina commented on July 17, 2024

@Shawn-Twinmaple We could do this

void DoStuff() => this.Data = this.Data ?? this.device?.ReadDataFromStream();

from csharplang.

jnm2 avatar jnm2 commented on July 17, 2024

@Thaina The shorthand for that will be ??=. Shawn is asking for a shorthand where this.Data is set to this.device?.ReadDataFromStream() if the latter is not null, regardless of whether this.Data was previously null.

from csharplang.

Thaina avatar Thaina commented on July 17, 2024

@jnm2

void DoStuff() => this.Data = this.device?.ReadDataFromStream() ?? this.Data;

?

from csharplang.

jnm2 avatar jnm2 commented on July 17, 2024

@Thaina Sort of, but not quite. In your example, you end up setting this.Data = this.Data if ReadDataFromStream returns null, but this can have side effects.

If you read Shawn's comment, he has the exact code you're looking for.

from csharplang.

Thaina avatar Thaina commented on July 17, 2024

@jnm2 I just think he just want to make it shorter to write. And so if it just a field I think it would have no side effect

If we need to avoid side effect for property too, well, maybe we need another feature request I have seen about allow putting expression in operator

void DoStuff() => this.Data = this.device?.ReadDataFromStream() ?? return;

from csharplang.

jnm2 avatar jnm2 commented on July 17, 2024

@Thaina Yes, that's exactly what he (and I) have just said. He wants it to be shorter to write.

I really want that ?? return feature (it just keeps coming up for me for other reasons) but I think it's already been turned down by the LDT (link). Also, it's not general enough to solve what Shawn is asking for. Imagine three of these statements in a row. You can't use ?? return more than once per method.

from csharplang.

Shawn-Twinmaple avatar Shawn-Twinmaple commented on July 17, 2024

@Shawn-Twinmaple We could do this

void DoStuff() => this.Data = this.device?.ReadDataFromStream() ?? this.Data;

Yep exactly.

That become this:
void DoStuff() => this.Data ?!= this.device?.ReadDataFromStream();
In this way, the need to re-assign to itself is simply short-circuited away.

Since both ! and != are already implemented negation operators I'm not really sure which "operator symbology" would work best for this.

Symbology aside
??= is great for null coalescing assignments, but not-null assignments are also a problem too, for the same reason.

Ideally there would be a solution both for null and not-null assignments, as they are both very common place occurrences in code found everywhere.

The proposed solution must work with nullable valuetypes and nullable reference types.
It must also work with non-nullable value types and non-nullable reference types.

I have attached some test examples that I believe covers all 4 of those cases for both proposed operators...
160 lines of code, far too much to post here.
Comments, Problems and Solutions for each case are all in the file.
test_examples.zip

I think the two operators really go hand-in-hand just like == and != does today;
but as suggested, this might need to be in its own feature request...

from csharplang.

jnm2 avatar jnm2 commented on July 17, 2024

@333fred and team, you're the best. Thanks for this!

from csharplang.

gafter avatar gafter commented on July 17, 2024

See https://github.com/dotnet/csharplang/blob/master/meetings/2019/LDM-2019-04-15.md#result-type-of--expression

from csharplang.

wanton7 avatar wanton7 commented on July 17, 2024

Does this feature mean I can finally use (list ??= new List<int>()).Add(7); instead of (list = list ?? new List<int>()).Add(7); in C# 8.0?

from csharplang.

yaakov-h avatar yaakov-h commented on July 17, 2024

@333fred yay, thanks!

from csharplang.

ufcpp avatar ufcpp commented on July 17, 2024

Is it possible to make LHS of the null-coalescing assignments by-ref?

using System;

class Program
{
    static void Main()
    {
        string[] values = new string[1];

        // OK
        ref var r1 = ref values[0];
        r1 ??= "abc";
        Console.WriteLine(values[0]);

        // NG
        ref var r2 = ref values[0] ??= "default string";
    }
}

from csharplang.

CoderVision avatar CoderVision commented on July 17, 2024

I love the idea of the ??= feature! I have been periodically checking updated compilers to see if it is included and was happy to see that it has a preview status.

from csharplang.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.