Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow using on non disposable and skip using when object is null #8004

Closed
Thaina opened this issue Jan 16, 2016 · 24 comments
Closed

Allow using on non disposable and skip using when object is null #8004

Thaina opened this issue Jan 16, 2016 · 24 comments

Comments

@Thaina
Copy link

Thaina commented Jan 16, 2016

From pattern matching proposal https://github.com/dotnet/roslyn/blob/future/docs/features/patterns.md

I don't like syntax if (expr is Type v) { // code using v } It not so readable

So I want to propose using anything for constraint scope.

using(var text = "Hello")
{
   Console.WriteLine(text); //// Hello
}

Console.WriteLine(text); //// Compiler error, no text available here

Then I want to propose syntax using?
Which will work like if. If the variable inside that using is null then it will skip all the thing inside

string text = null;
using?(var t = text)
{
   Console.WriteLine(t); //// Will not come in here
}

Console.WriteLine(t); //// Compiler error, no t available here

ps. Alternatively I would like to let we could use operator ?? after declaration and it will both add variable to scope and return true/false
I mean like this if ((var v = expr as Type)??) { // code using v } Maybe better

@asvishnyakov
Copy link
Contributor

Stop using operators (like ? or !) in keywords. It's bad idea.

@alrz
Copy link
Member

alrz commented Jan 16, 2016

Your first example is something you gain with blocks by definition,

{
  var text = "Hello";
  Console.WriteLine(text); 
}
Console.WriteLine(text); // Compiler error, 'text' is not available here

And your second example is nothing more than just a null-check,

string text = null;
if(text != null)
{
   Console.WriteLine(text);
}

And I didn't understand what this has to do with pattern matching and what's "not so readable" about it.

@Thaina
Copy link
Author

Thaina commented Jan 16, 2016

@alrz Didn't you see that in that proposal there are if (expr is Type v) { // code using v } ?

That so do the same nothing more than just a null-check

@alrz
Copy link
Member

alrz commented Jan 16, 2016

@Thaina Actually, in this case, it's a type check and also you can use any pattern that mentioned in the spec draft. I suggest you to read it once again.

@Thaina
Copy link
Author

Thaina commented Jan 16, 2016

@alrz And if you see my proposal I actually use it for type check. Because if you use as keyword on the object that isn't that type it would be null immediately

I don't like it that if keyword will used to add variable, not to mention the syntax if (expr is Type v) is not obvious meaning. Bad syntax in my opinion

So I was go other way around, use a using keyword that already has syntax used for add variable to scope. and also ability to skip itself if that variable is null. That's it

@Thaina
Copy link
Author

Thaina commented Jan 16, 2016

@asvishnyakov Actually I also think that maybe using should always skip its block when the thing it get is null. So it may not need ?

Then we would do any pattern matching logic for using and make it skip by set the variable for using to null

@asvishnyakov
Copy link
Contributor

@Thaina Your example has no relation to pattern matching.

if (expr is Type v) { // code using v }

is equivalent of

var v = expr as Type;
if (v != null) { // code using v }

Your using proposal looks like you want to define new scope in code like

var func = () =>
{
   var text = "Hello";
   Console.WriteLine(text); //// Hello
}
func();

Console.WriteLine(text); //// Compiler error, no text available here

@Thaina
Copy link
Author

Thaina commented Jan 16, 2016

@asvishnyakov Not at all

Let me state it clearly. What I really want is

var v = expr as Type;
if (v != null) { // code using v }

While the original is try to propose
if (expr is Type v) { // code using v }

I want to propose
using? (var v = expr as Type) { // code using v }
or
using (var v = expr as Type) { // code using v if v is not null, if v is null then do nothing in here }

@alrz
Copy link
Member

alrz commented Jan 16, 2016

is is an existing operator that does the type checking, the point of pattern matching is to extending it to be able to match the target variable unto a pattern which potentially introduce variables into the scope. The thing is, it's a conditional anyway, so actually it would be good to use if for this purpose (however, in case of a complete pattern you can use #6400 without else). using( ... ) on the other hand, has a specific meaning and it's not just for introducing a variable.

@Thaina
Copy link
Author

Thaina commented Jan 16, 2016

@alrz as is also operator that does type checking by return null if it is not that type. And so I want to use it as pattern matching that if it not match the pattern it will return null

Then we could let using to handle the null by skip it. Instead of try to make if do thing like using. I would prefer let using do thing like if

@asvishnyakov
Copy link
Contributor

@Thaina @alrz Yep, I don't like if (expr is Type v) { // code using v } syntax too. But using? I don't like too. We already have if statement. So if (expr is Type) { var v = (Type)expr; ... } is still preferred for me.

@alrz
Copy link
Member

alrz commented Jan 16, 2016

@asvishnyakov As long as you don't mind double type checks, it's ok.

@Thaina
Copy link
Author

Thaina commented Jan 16, 2016

@asvishnyakov OK So now I would like to propose that using should allowed to everything not only disposable, and then I would like to propose that using should always skip when it get null

So the syntax will be just
using (var v = expr as Type) { // code using v only if v is not null }
How do you think then?

@Thaina Thaina changed the title Allow using on non disposable and null skip using Allow using on non disposable and skip using when object is null Jan 16, 2016
@asvishnyakov
Copy link
Contributor

@alrz If you propose any other syntax, where we can see both casting and assigning, I will support you. Because now we always use = operator to assign something to variable. We can't use it in “if pattern matching” because it will looks like assigning boolean value to variable. We also can't use => for the same reason. I like “switch-case pattern matching”, but not “if pattern matching”

@Thaina
Again, we already have if statement. It's not clear that using keyword maybe used to check var v = expr as Type to null. And how about other patterns? With current pattern matching proposal we can use any expression, not only as-is.

@Thaina
Copy link
Author

Thaina commented Jan 16, 2016

@asvishnyakov That's why I go other way around

I try to reuse using and as instead of if and is. So you can use = because you really assign what you want to that variable. And by let using can skip when it get null. You can just use using to do type checking and assign variable also only in that block scope in one line

I also want to propose that we should be able to use as to do pattern matching in the same way as is. And get null when it not match, so we will check if it null or let it be assigned in using scope too

@asvishnyakov
Copy link
Contributor

@Thaina Ok

@bondsbw
Copy link

bondsbw commented Jan 17, 2016

@Thaina

@asvishnyakov OK So now I would like to propose that using should allowed to everything not only disposable, and then I would like to propose that using should always skip when it get null

So the syntax will be just
`using (var v = expr as Type) { // code using v only if v is not null }``
How do you think then?

This would be a breaking change. Currently the block is executed regardless of the value inside the using clause being null:

using (null) { Console.WriteLine("This line always executes."); }

@Thaina
Copy link
Author

Thaina commented Jan 17, 2016

@bondsbw Well, that's why firstly I want to propose using? syntax

But somehow I think we should not allow using(var a = (object)null) anyway because using should always need real object to disposed
Currently now it just check null at the end but why it should be allowed in the first place? What benefit of it to let it handle null while people use using to get something in scope to work with?

I think it should work like for(var a = b as A; a != null;a = null)
Or maybe I should propose new keyword like usingif(var a = b as A) ?

@walkindude
Copy link

IMO Kotlin got this right: https://kotlinlang.org/docs/reference/basic-syntax.html#using-type-checks-and-automatic-casts

I don't know if this could be done in C# without breaking compatibility, but I thought I would throw this in.

@bondsbw
Copy link

bondsbw commented Feb 9, 2016

@walkindude That is interesting, and I suspect you are correct that it would be a breaking change for C# due to non-virtual call resolution. Pattern matching will get us close though.

if (obj is string s && s.Length > 0)
    return s.Length;

@Thaina
Copy link
Author

Thaina commented Apr 29, 2016

@bondsbw I would support Kotlin instead. I really hate that pattern matching syntax

I think implementation will just be the same. It could be compile time temporary variable

I mean when we do this

if (obj is string && obj.Length > 0)
    return obj.Length;

At compile time it could be temporarily translate to

var _tmp_obj_string = obj as string;
if (_tmp_obj_string != null && _tmp_obj_string.Length > 0)
    return _tmp_obj_string.Length;

And it should work just fine

@Thaina
Copy link
Author

Thaina commented May 25, 2016

Just have another idea that would make it work like kotlin

maybe just this syntax

object obj = "";
using(obj as string)
{
    var length = obj.Length; // obj temporarily became string in this block
}

This difference from normal using that it has no = symbol. So it differ from existing code. And if it not contain = symbol then it not dispose, but skip this block if obj as string is null instead

@stepanbenes
Copy link

stepanbenes commented May 25, 2016

@Thaina using statement already supports expression as its argument (besides declaration syntax with = symbol)

@Thaina
Copy link
Author

Thaina commented May 25, 2016

Thanks @stepanbenes . I forgot that because never see anyone use it. But this was impossible anyway

So I need to redo proposal to #11553 and close this

@Thaina Thaina closed this as completed May 25, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

8 participants