Visual Studio 2017: March 7th


  • Impossible Mission - B

    @CreatedToDislikeThis said in Visual Studio 2017: March 7th:

    @masonwheeler Yeah, could be.

    But I think there's still a place for local functions alongside lambdas -

    int doMyThing (int x)
    {
    ... some code ..
    }

    Just reads better than

    var doMyThing = (int x) =>
    {
    ... some code ..
    }

    Yeah, C#'s lambda syntax is ugly. But then again, have you ever seen any language whose lambda syntax isn't ugly? :P


  • FoxDev

    @masonwheeler said in Visual Studio 2017: March 7th:

    @RaceProUK said in Visual Studio 2017: March 7th:

    • Generalized async return types: Sounds useful, though I'd prefer a way to avoid the Task<> syntax in the first place.

    Meh. Is there anything wrong with Tasks, that you need your own ❄ task class instead?

    There's nothing wrong with Tasks at all, but given (almost) all async methods have to return a Task of some description, why not allow the omission of the superfluous Task/Task<> syntax? The async is enough, surely?



  • @RaceProUK What confuses me I've always used callbacks and thread counting in old ASP.NET code. Is the await keyword.

    e.g. IHttpAsyncHandler

    BeginProcessRequest(HttpContext, AsyncCallback, Object);
    
    EndProcessRequest(IAsyncResult);
    
    ProcessRequest(HttpContext)
    

    Works conceptually similar a callback in jQuery / JavaScript.

    Now when I have Async Task<MyObjec> I normally have to have await somewhere. I thought the whole point was that it just executed once it could in the OWIN event loop?


  • FoxDev

    @lucas1 I'll refer you to Eric Lippert, who does a far better job of explaining async/await than I ever could.



  • @RaceProUK I always understood it as one way to make sure that your UI thread isn't blocked while at the same time making your code more understandable by not having to descend into callback hell (and the associated problems like scoping). There are other uses, of course :)


  • FoxDev

    @Rhywden Yeah, that's basically it ;)



  • @Rhywden In web stuff you are more likely to run out of threads on the server. If you implement IHttpAsyncHandler and don't debounce server side in one form or another, the server will run out of threads.

    I suppose if it was a WinForms app that might be a problem. But you should update the UI via events tbh. That is what Microsoft used to recommend.



  • @lucas1 said in Visual Studio 2017: March 7th:

    @Rhywden In web stuff you are more likely to run out of threads on the server.

    Erm, since when does the client's UI have anything to do with the server?



  • @Rhywden
    If you make a lot of Ajax requests without denouncing either but rate limiting and/or debouncing client side, the server will run out of threads on the server.



  • @lucas1 said in Visual Studio 2017: March 7th:

    @Rhywden
    If you make a lot of Ajax requests without denouncing either but rate limiting and/or debouncing client side, the server will run out of threads on the server.

    That will happen regardless of using async/await or callbacks.



  • @RaceProUK said in Visual Studio 2017: March 7th:

    Pattern matching: Hell yes! The power this will give to if and switch is going to be so worth it!

    This is a fucking mess. That's the example they give:

    if (o is int i || (o is string s && int.TryParse(s, out i)) { /* use i */ }
    

    So is is a pure boolean operator, except when it has a type name after in which case it's a cast and introduces a variable, that variable is scoped to the outer scope which means you can use it in the if statement but only for conditions which run when the result of is is true (I think?), and you can use it as an out parameter but don't add a type name because that declares a variable too...

    @RaceProUK said in Visual Studio 2017: March 7th:

    Tuples: These look pretty damn useful too, and should be easier to use than the Tuple<> family. The IntelliSense improvements alone will be worth it.
    Deconstruction: See Tuples.

    Looks like it's going to encourage quick-and-dirty sloppy programming where instead of properly declaring your data structures, you just randomly construct overblown impromptu types together. Tuples are a kludge. They should look like a kludge. Declare a fucking class if you're going to let your data structure leave your method.

    @RaceProUK said in Visual Studio 2017: March 7th:

    Local functions: This is one of the things I like about JavaScript, and it's good to see C# adopt them, as long as they allow for recursion, like the JS ones do.

    Why not declare it in the class scope as a private function? If you need to distinguish between local functions and private class functions, then your function is doing too much.

    And you can just make an inline lambda anyway. Which should even support recursion with a closure over the delegate object. Looks pointless.

    @Magus said in Visual Studio 2017: March 7th:

    @CreatedToDislikeThis Ref returns just seem hard to understand.

    I think a good similar feature would be a better way to deal with field selectors than breaking down an Expression<Func<>> to get the property name and use it via reflection, but I'm not quite sure you can do that with the refs.

    @CreatedToDislikeThis said in Visual Studio 2017: March 7th:

    The main issue with using lambdas/delegates as local functions is that:

    You can't assign them to "var" - you have to specify their type explicitly (due to it being possible to treat them either as a delegate or as an expression tree).
    You can't use recursion unless (IIRC) you split the declaration of the variable and its assignment into separate lines.

    So having a new syntax that does away with these restrictions* is definitely a good thing, especially as the syntax is identical to the existing method declaration syntax, so you can think of it as an extension of an existing function syntax rather than a new one.

    That's very little benefit for a new feature. You can declare it and you can recurse via a closure, it just takes a line or two more. You shouldn't be doing it much anyway, putting the functions in the class scope instead, so I don't mind the friction.


  • Notification Spam Recipient

    @Adynathos said in Visual Studio 2017: March 7th:

    You can install already.
    Installs faster, choosing "workflows" makes it a bit hard to find what you want, but its ok.
    Upon a quick look I do not see any difference between 2017 and 2015.
    Unreal Engine still prefers to work with 2015.

    You're in unreal too? Hey, not to derail the discussion, but does iterative cooking work for you? Every time I stage it cooks the whole damn thing...



  • @Rhywden I am not talking about Async / Await callbacks, I am talking about IHttpAsyncHandler as previously linked. You will notice it has a Begin and EndProcess methods. These have been around since .NET 1.1 or maybe earlier.

    Obviously you will run out of threads if you send the server enough requests. However it is much worse because you can queue an infinite amount of call backs i.e. it won't just flat out deny the requests via 500 or similar errors when the requests are made synchronously (I can't remember how it works now in IIS because I haven't encountered it in years). So you need especially make sure you limit rate when using handlers like IHttpAsyncHandler

    To be honest it already apparently you are more interested in looking for gotchas. So this will be my last reply to you on this topic.



  • @Maciejasjmj said in Visual Studio 2017: March 7th:

    Looks like it's going to encourage quick-and-dirty sloppy programming where instead of properly declaring your data structures, you just randomly construct overblown impromptu types together. Tuples are a kludge. They should look like a kludge. Declare a fucking class if you're going to let your data structure leave your method.

    A lot of tuple usage will be to allow a function to return "multiple" values - that's not much different than allowing a function to receive multiple values, IMO.



  • @CreatedToDislikeThis Previously you would make a DTO or something similar to represent the data structure properly.

    Maybe I am stuck into my .NET 2.0 / Java 1.5 OOP programming ways.


  • FoxDev

    @lucas1 said in Visual Studio 2017: March 7th:

    Obviously you will run out of threads if you send the server enough requests.

    This is an area async/await can help. By not blocking on expensive I/O (and similar), those threads can be reused to serve other requests until the expensive operation finishes.



  • @RaceProUK That was what I was getting at with @Rhywden. I was doing it "manually" before this was part of .NET. It makes more sense now I can see how it relates to the much lower level stuff I have done before.

    (I don't want to be having to manage threads, I am not very good at it).



  • @CreatedToDislikeThis said in Visual Studio 2017: March 7th:

    @Maciejasjmj said in Visual Studio 2017: March 7th:

    Looks like it's going to encourage quick-and-dirty sloppy programming where instead of properly declaring your data structures, you just randomly construct overblown impromptu types together. Tuples are a kludge. They should look like a kludge. Declare a fucking class if you're going to let your data structure leave your method.

    A lot of tuple usage will be to allow a function to return "multiple" values - that's not much different than allowing a function to receive multiple values, IMO.

    Eeeh... My philosophy is "accept input in sloppy format, but return a nice and specific value". The same reason why you'd accept an IEnumerable, but return a List, or accept IWhatever but return ConcreteWhatever unless you have a good reason to hide the details.

    Plus you just know some library writer will try implementing the Go-style error handling.


  • FoxDev

    @lucas1 That's the big win with async/await for me: I can have all the asynchrony I want, with none of the hassle :D


  • area_pol

    @Tsaukpaetra said in Visual Studio 2017: March 7th:

    You're in unreal too? Hey, not to derail the discussion, but does iterative cooking work for you? Every time I stage it cooks the whole damn thing...

    Good to see someone else from Unreal :)
    Which platform do you build for? For Windows and Linux it seems to cook just once (again if you switch to shipping mode), but for Android it repeats a very long cooking/building procedure every time.



  • @Maciejasjmj No you should return the most generic type and take the most generic type.

    If it is an interface going in and coming out the internal bits and pieces in the method shouldn't change.



  • @lucas1 said in Visual Studio 2017: March 7th:

    you should return the most generic type and take the most generic type.

    That would be object, I suppose?

    It boils down to what guarantees you do and don't want to make about your method, but if you're building a List and you know you'll always be building a List there, there's no other reason to return an IEnumerable than pissing off the caller who now has to pointlessly ToList() your output.



  • @Maciejasjmj

    That would be object, I suppose?

    The most generic type that is reasonable I should have said. I suppose there would be some dickhead returning IObject

    It boils down to what guarantees you do and don't want to make about your method, but if you're building a List and you know you'll always be building a List there, there's no other reason to return an IEnumerable than pissing off the caller who now has to pointlessly ToList() your output.

    IList<T> still more abstract than List<T>

    I suppose there are going to be very few situations where people have implemented their own IList<T> but it still decouples it from the concrete implementation.

    TBH if I was writing it I wouldn't care most of the time unless I had third party devs working with my libs.


  • Winner of the 2016 Presidential Election

    @Maciejasjmj said in Visual Studio 2017: March 7th:

    The same reason why you'd accept an IEnumerable, but return a List, or accept IWhatever but return ConcreteWhatever unless you have a good reason to hide the details.

    Maybe I'm spending too much time in C++ land, but "it makes the API more robust to change" is a pretty good reason for never declaring concrete classes as return types unless you absolutely have to.



  • @asdf You are right. C# is no different in that respect.


  • Winner of the 2016 Presidential Election

    @Maciejasjmj said in Visual Studio 2017: March 7th:

    if you're building a List and you know you'll always be building a List there, there's no other reason to return an IEnumerable than pissing off the caller who now has to pointlessly ToList() your output

    Why would the caller even do that? What List feature does he need which is not available for IEnumarable? If all your API promises is to generate a sequence to X, I see no reason to declare List as the return type. What if you want to construct it lazily? Why should the caller care?



  • @Maciejasjmj said in Visual Studio 2017: March 7th:

    than pissing off the caller who now has to pointlessly ToList() your output.

    Return IList<T> then. It is still less coupled than using List<T>.



  • @asdf said in Visual Studio 2017: March 7th:

    What List feature does he need which is not available for IEnumarable

    There are quite a few.

    E.g.

    Add<T>(myobject)
    

    IEnumerable is the most basic Collection with an Iterator really.

    @Maciejasjmj isn't massively wrong. But there are better ways I believe to deal with it.


  • Winner of the 2016 Presidential Election

    @lucas1 OK, I was assuming the method was supposed to return some immutable sequence. If the sequence must be mutable, then you need a more specific interface.



  • @asdf Err what? Oh you mean you can't change the list. Remember I am a Front End Developer first and C# is something I have picked up over time.

    No IEnumerable for the most part means you can do a foreach loop on it in C#. I am sure there is more important differences but for the sake of this conversation it isn't important ... before the pedants come in.



  • @asdf said in Visual Studio 2017: March 7th:

    What List feature does he need which is not available for IEnumarable?

    Random access, for one.

    @asdf said in Visual Studio 2017: March 7th:

    If all your API promises is to generate a sequence to X, I see no reason to declare List as the return type. What if you want to construct it lazily? Why should the caller care?

    Again, if you have good reasons to not promise a List<T> (for example, if you anticipate that the method might be eventually rewritten into a lazy evaluation), it's fine. But all too often I've seen methods that start with var result = new List<T>(), do things that aren't really feasible or necessary to do lazily, and return IEnumerable<T> just because that's what you should do. If you have a choice between giving the caller an IEnumerable and a List (or IList, which has the same capabilities), and there's no apparent drawback to the latter, why would you go with the former?



  • This post is deleted!

  • Notification Spam Recipient

    @lucas1 said in Visual Studio 2017: March 7th:

    (I don't want to be having to manage threads, I am not very good at it).

    Threading is hard, I don't expect many to every really do it correctly...



  • @Maciejasjmj said in Visual Studio 2017: March 7th:

    and there's no apparent drawback to the latter, why would you go with

    EDIT: 2nd and 3rd answers seem to sell the case for me.


  • Winner of the 2016 Presidential Election

    @Maciejasjmj
    OK, random access is another valid use case for a more specific interface.

    I don't really understand your last argument for using List instead of IList. Why would you use a concrete class when the interface is just as powerful and allows switching the implementation without breaking the API, if necessary?



  • @asdf said in Visual Studio 2017: March 7th:

    Why would you use a concrete class when the interface is just as powerful and allows switching the implementation without breaking the API, if necessary?

    Because most people won't care. Most C# stuff is done by people creating crappy winforms apps for some business they can't wait to leave at 5pm.


  • Notification Spam Recipient

    @Adynathos said in Visual Studio 2017: March 7th:

    @Tsaukpaetra said in Visual Studio 2017: March 7th:

    You're in unreal too? Hey, not to derail the discussion, but does iterative cooking work for you? Every time I stage it cooks the whole damn thing...

    Good to see someone else from Unreal :)
    Which platform do you build for? For Windows and Linux it seems to cook just once (again if you switch to shipping mode), but for Android it repeats a very long cooking/building procedure every time.

    Yeah, our setup must be broken or something. Building for Windows Development, there's a log message about invalidating cook every run so it starts from scratch every time. Oh well...



  • @asdf said in Visual Studio 2017: March 7th:

    I don't really understand your last argument for using List instead of IList.

    That's because I didn't make it. I guess that wasn't clear. IList is fine, since it lets the caller do anything they could do with a List (save for some reflection tricks). IEnumerable is bad because it only supports foreach and cuts off the random access, or the modifications.

    @lucas1 said in Visual Studio 2017: March 7th:

    EDIT: 2nd and 3rd answers seem to sell the case for me.

    The first answer refers to IEnumerable being more flexible than an IList. Which it is - as an input parameter. As an output, it makes your API less flexible, since it limits what the caller can do with the returned object.

    The second answer is true if you actually are returning an IEnumerable from an outside API (like a result of Where()), which can be deferred. If you're actually returning a List, just presenting it as its IEnumerable interface, you get none of the benefits.



  • @Maciejasjmj said in Visual Studio 2017: March 7th:

    As an output, it makes your API less flexible, since it limits what the caller can do with the returned object.

    How? They can do a ToList<T>() themselves if they wish. You shouldn't be doing it for them.

    If you're actually returning a List, just presenting it as its IEnumerable interface, you get none of the benefits.

    Again you shouldn't be caring what they do with it. The point is that you are giving them a collection of objects and they can do what they like with it. With the most generic type you give them the most flexibility.

    It is irrelevant if they act like retards and convert to list first ... that is their problem not yours.



  • @lucas1 said in Visual Studio 2017: March 7th:

    How? They can do a ToList<T>() themselves if they wish. You shouldn't be doing it for them.

    But in the scenario I'm describing, it's utterly pointless to require the caller to do that since you are already giving them a List<T>. You're just pretending it's not a List<T>.

    @lucas1 said in Visual Studio 2017: March 7th:

    The point is that you are giving them a collection of objects and they can do what they like with it. With the most generic type you give them the most flexibility.

    ...how is that more flexible? There's nothing an IList<T> can't do that an IEnumerable<T> can, and IList<T> does significantly more on top of that. So isn't it more flexible to give the caller the type that has more options on it?



  • @Maciejasjmj said in Visual Studio 2017: March 7th:

    But in the scenario I'm describing

    Which is the entire point. Your scenario is your own. It isn't mine, or it is general.


  • Notification Spam Recipient

    @lucas1 said in Visual Studio 2017: March 7th:

    @Maciejasjmj said in Visual Studio 2017: March 7th:

    As an output, it makes your API less flexible, since it limits what the caller can do with the returned object.

    How? They can do a ToList<T>() themselves if they wish. You shouldn't be doing it for them.

    If you're actually returning a List, just presenting it as its IEnumerable interface, you get none of the benefits.

    Again you shouldn't be caring what they do with it. The point is that you are giving them a collection of objects and they can do what they like with it. With the most generic type you give them the most flexibility.

    It is irrelevant if they act like retards and convert to list first ... that is their problem not yours.

    For that matter, why give an IEnumerable at all? If all they actually need is a collection of objects, why not give back Array<T>?



  • @Tsaukpaetra Because you can't use Lazy Evaluation. Arrays are Eager.

    EDIT: I wasn't 100% sure

    Oh there is more reasons to use IEnumerable I forgot about the yield keyword

    yield return adds one item to the returned IEnumerable<T> each time it is called, but it does not end the function as a normal return would. The function ends when flow of control reaches the end of the function body.
    Using yield return makes the code shorter than creating and populating e.g. a list, but that’s only part of the strength. The real power lies in the lazy evaluation.

    There is more here from Jon Skeet which the the Stack Overflow God:

    This is quite interesting. I am going to have to read more about this tomorrow. But there definitely seems to be some advantages for using IEnumerable other than "more generic"


  • FoxDev

    @Tsaukpaetra Write a Fibonacci generator that returns Array<T> :P


  • Notification Spam Recipient

    @RaceProUK said in Visual Studio 2017: March 7th:

    @Tsaukpaetra Write a Fibonacci generator that returns Array<T> :P

    I just feel like they're arguing in circles. Just use the most generic type that satisfies needs while providing the necessary functionality. If the downstream developer needs it elsewise, they're undoubtably going to have to convert it anyways, so why do extra work for no benefit?



  • @lucas1 said in Visual Studio 2017: March 7th:

    Which is the entire point. Your scenario is your own. It isn't mine, or it is general.

    Obviously if you're not actually constructing a List<T> you shouldn't return a List<T>, and if you actually do support lazy evaluation then you should return IEnumerable<T> because that's what you have.

    The scenario we were talking about is that you have an object of some concrete type as a result of your processing, and the question is whether you should return that concrete type (or an interface that's equivalent in functionality), or whether you should return a more general interface that cuts some of that functionality off.

    Like... Computer supports IPaperweight, doesn't it? And when you write a method and need a paperweight, you won't write it to accept Computer, or RealPaperweight, because you want to give the caller the flexibility - they can just pass you their Computer and don't have to go looking for a real paperweight, or convert it into one.

    But when you do your processing in the method and end up with a Computer, there's rarely a good reason to return it as an IPaperweight - especially if you know your process will never change to return a Rock, or WoodenSlab. You wouldn't sell a computer as a paperweight, because your customer might want to do some computing with it, and if it's working then why shouldn't they be able to?



  • @Maciejasjmj said in Visual Studio 2017: March 7th:

    The scenario we were talking about is that you have an object of some concrete type as a result of your processing, and the question is whether you should return that concrete type (or an interface that's equivalent in functionality), or whether you should return a more general interface that cuts some of that functionality off.

    So does it matter if you call ToList() at the end of the method or the start of another one?

    We were initially talking about the general rule. The general rule if you want to decouple your code it to take the most generic collection and output the most generic collection.

    There is always go to be times where that doesn't make sense.

    It is just a rule of thumb and there are some good reasons I posted above.

    https://what.thedailywtf.com/topic/22113/visual-studio-2017-march-7th/93



  • @Tsaukpaetra Yes we are. I posted all the relevant information.



  • @Tsaukpaetra said in Visual Studio 2017: March 7th:

    Just use the most generic type that satisfies needs while providing the necessary functionality.

    Point is, you know what the necessary functionality is for your method (so you can accept general input parameters), but you don't really know what the necessary functionality is for the caller (so a general return value is a bit worse).


  • Notification Spam Recipient

    @Maciejasjmj said in Visual Studio 2017: March 7th:

    @Tsaukpaetra said in Visual Studio 2017: March 7th:

    Just use the most generic type that satisfies needs while providing the necessary functionality.

    Point is, you know what the necessary functionality is for your method (so you can accept general input parameters), but you don't really know what the necessary functionality is for the caller (so a general return value is a bit worse).

    So, if you got something with specific functionality, why make it worse if you don't have to?


Log in to reply