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

Please support 'var' as function return type instead of return a dynamic #13656

Closed
xaqi opened this issue Sep 7, 2016 · 25 comments
Closed

Please support 'var' as function return type instead of return a dynamic #13656

xaqi opened this issue Sep 7, 2016 · 25 comments

Comments

@xaqi
Copy link

xaqi commented Sep 7, 2016

Anonymous class is convenient, especially for linq. But it's not convenient to return an anonymous class in function. So I have to define a returned type class (boring) or use dynamic (lose VS autocomplete and compile checking).
Why not support 'var' instead of 'dynamic'? VS is able to recognize what the var is by return value, thus the Foo function returns a strongly-typed value, much better than dynamic and needn't define a class.

void Main()
{
       var name = Foo().Name;
}
public dynamic Foo()
{
       return new { Name = "" };
}

public var Foo()
{
       return new { Name = "" };

}

Actually, what troubles me is defining the one-time used type. I must create a file or look for somewhere to write the code. And when the function is useless any more, I have to find the define and remove it.
Exposing anonymous types is one solution. Since you guys don't like it, I have another idea.
@dsaf @svick @ufcpp @agocke @eyalsk How about defining a class while return, like this:
public User Foo()
{
       return new class User { Name = "" };
}

@dsaf
Copy link

dsaf commented Sep 7, 2016

You are asking for three things:

  1. new kind of inference Add more type-inferencing to C# #17
  2. to expose anonymous types Proposal: Declaration of anonymous type  #8404 (comment)
  3. to ammend current release plan https://github.com/dotnet/roslyn/blob/master/docs/Language%20Feature%20Status.md

@svick
Copy link
Contributor

svick commented Sep 7, 2016

The new tuples feature (#347) planned for C# 7.0 aims to improve this. With it, you will be able to write:

void Main()
{
       var name = Foo().Name;
}

public (string Name, int Age) Foo()
{
       return (Name: "", Age: 0);
}

It doesn't work in your exact case, because single-value tuples are not supported.

@dsaf
Copy link

dsaf commented Sep 7, 2016

@svick I can't help but think of this:

public let Foo() => (Name: "", Age: 0);

...because single-value tuples are not supported...

The only solution is better method names I guess.

@xaqi
Copy link
Author

xaqi commented Sep 7, 2016

The tuple is cool. But still need to define the item type and it can't work with complex type such as return new{a=new{b=1}}.

@svick
Copy link
Contributor

svick commented Sep 7, 2016

@dsaf You can do it the other way around:

public (string Name, int Age) Foo() => ("", 0);

@ufcpp
Copy link
Contributor

ufcpp commented Sep 7, 2016

@AndyQi Tuple can work with complex type such as (a : (b: 1)).

@dsaf
Copy link

dsaf commented Sep 7, 2016

@svick true, but it puts property names far from values. Though would be kind of consistent with #35.

@xaqi
Copy link
Author

xaqi commented Sep 7, 2016

Thanks @ufcpp, resolved my problem, but return a anonymous class looks more convenient.
@dsaf haha, I'm not asking for 3), I want it now but I know you guys need time to develop and test.

@xaqi xaqi changed the title Please support 'var' as function return type in next C# version, much better than 'dynamic' Please support 'var' as function return type instead of return a dynamic Sep 7, 2016
@agocke
Copy link
Member

agocke commented Sep 7, 2016

Re additional type inference, see my comment here: #17 (comment)

@iam3yal
Copy link

iam3yal commented Sep 8, 2016

Maybe related to #5161.

@omariom
Copy link

omariom commented Sep 9, 2016

I don't like that to find what a method returns I will need to scan through all its lines.
👎

@xaqi
Copy link
Author

xaqi commented Sep 10, 2016

@omariom Needn't scan all the lines, move the mouse pointer to the var or just call the method, then vs will tell you what the var is.
@agocke Yes, it's bad for code reuse and code conventions, since you guys are building huge projects, in which they are important. But for me, I ofen write small tools/scripts and simple web pages. I don't like to define so much one-time used types and want the code to be fewer.
I’m not recommend to use var anywhere, just for small projects or private methods. It’s also easy to replace the var with defined types when necessary.

@iam3yal
Copy link

iam3yal commented Sep 10, 2016

@AndyQi I don't really agree with this proposal exactly, in the far past I'd probably agree with you on exposing anonymous types but since the introduction of tuples and future records I don't think it's worth the troubles but I do think that there's more room for more type inference, especially when it comes to generics but that's another issue.

@iam3yal
Copy link

iam3yal commented Sep 14, 2016

@AndyQi

Actually, what troubles me is defining the one-time used type. I must create a file or look for somewhere to write the code. And when the function is useless any more, I have to find the define and remove it.

Dead code is easy to remove, you can do it manually through the IDE using tools like ReSharper, Roslyn Analyzers, or automatically in a build step or something.

public User Foo()
{
       return new class User { Name = "" };
}

That's similar to records, the only thing is you have to define it before its usage, what if two methods returns User but a different kind of User? and if they share the same User why not define it beforehand?

@dsaf
Copy link

dsaf commented Sep 14, 2016

@AndyQi

...I must create a file...

I too feel that it's often an overkill. Unfortunately the current practice is one file per type.
Anyway, what is your problem with new tuples, again?

@xaqi
Copy link
Author

xaqi commented Sep 14, 2016

@eyalsk You are right, that's a problem. I'll try tuple in C# 7.
@dsaf Tuples looks good, can it be serialized?
var result = (count: 5, sum: 20);
new JavaScriptSerializer().Serialize(result)="{count: 5, sum: 20}" or "{Item1:5,Item2:20}" ?

@iam3yal
Copy link

iam3yal commented Sep 14, 2016

@AndyQi Serialization is really a question of whether the serializer you use can handle it, the data is there.

@svick
Copy link
Contributor

svick commented Sep 14, 2016

@eyalsk Is it? If you look at @AndyQi's example, it's serializing just a tuple, there is no place to put the TupleElementNamesAttribute in that case, so I don't think the data is there.

If you're serializing an object that contains a tuple property, that's different.

@iam3yal
Copy link

iam3yal commented Sep 14, 2016

@svick

there is no place to put the TupleElementNamesAttribute in that case, so I don't think the data is there.

Why would you need to add it yourself? the compiler does it for you.. I'm not sure I understand you.

@svick
Copy link
Contributor

svick commented Sep 14, 2016

@eyalsk What I mean is that the compiler doesn't do it, because it can't.

This code:

var result = (count: 5, sum: 20);
new JavaScriptSerializer().Serialize(result);

is compiled into:

var result = new ValueTuple<int, int>(5, 20);
new JavaScriptSerializer().Serialize(result);

As you can see, the compiler didn't put TupleElementNamesAttribute (or any other way of saving the names into metadata) anywhere, because there is not place to put it.

@alrz
Copy link
Contributor

alrz commented Sep 14, 2016

I think this discussion belongs to #6949. Tuples should not be confused with "dictionaries".

@iam3yal
Copy link

iam3yal commented Sep 14, 2016

@svick You're right, my bad, didn't think this through so thank you for the enlightenment. :)

@TKharaishvili
Copy link

TKharaishvili commented Sep 20, 2016

I'm in favor of inferred function return types. There are quite many cases where specifying them just seems redundant. Actions in mvc being one of the examples:

public let Index()
{
    return View();
}

Would be quite nice instead of specifying IActionResult as the return type all over the place. I'm also in favor of the let keyword(or maybe no keyword at all if that's possible) instead of var because var kinda is short for variable and putting it in front of a function doesn't really sound appropriate.

Many small applications and small functions would benefit from this feature. As for the concerns @agocke has mentioned, in case of bigger projects and perhaps class libraries where return types are part of the documentation, it would be really simple to build a roslyn analyzer that requires developers to specify them explicitly on any of the public functions.

@iam3yal
Copy link

iam3yal commented Sep 21, 2016

@TKharaishvili I understand what you're saying but tbh this is actually bad imo, I'm all for type inference but this seems like taking C# too far, way too far.

What's the difference between let or whatever and specify the type? I see no real difference besides reducing the quality of the code in terms of readability.

Initially, iirc var was introduced due to anonymous types, nowadays, people use it more than I think they should but again that's purely subjective, however, I still think that there's still places for type inference in the language like in these cases #2319.

p.s. I think that there are few proposals discussing your suggestion that were closed because this is too radical. :)

@jcouv
Copy link
Member

jcouv commented Jul 29, 2017

We have been migrating language discussions and proposals to the csharplang repo. I'll go ahead and close the present issue.
Please re-open the discussion over there if you'd like. Thanks

@jcouv jcouv closed this as completed Jul 29, 2017
@jcouv jcouv self-assigned this Jul 29, 2017
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